/*
 * xLazyLoader 1.1 - Plugin for jQuery
 * 
 * Load js, css and  imgs
 *
 * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)
 * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
 *
 * Depends:
 *   jquery.js
 *
 *  Copyright (c) 2008 Oleg Slobodskoi (ajaxsoft.de)
 */

;(function($){

    $.xLazyLoader =  function ( method, options ) {
        if ( typeof method == 'object' ) {
            options = method;
            method = 'init';
        };
        var obj = {instance: new xLazyLoader(options, function(){
            delete obj.instance;    
        })};
        obj.instance[method](options);
    };
    
    $.xLazyLoader.defaults = {
        js: [], css: [], img: [],
        name: null,
        timeout: 20000,
        /* success callback for all files*/
        success: function(){}, 
        /* error callback - by load errors / timeout */
        error: function(){},
        /* complete callbck - by success or errors */
        complete: function(){},
        /* success callback for each file */
        each: function(){} 
    };

    var $head = $('head');
    
    function xLazyLoader ( options, deleteInstance )
    {

        var self = this,
            s = $.extend({}, $.xLazyLoader.defaults, options),
            loaded = [],
            errors = [],
            tTimeout,
            cssTimeout,
            toLoad = {js: s.js, css: s.css, img: s.img},
            files = []
        ;
        
        this.init = function ()
        {
            $.each(toLoad, function( type, f ){
                if ( typeof f == 'string' )        
                    f = f.split(',');
                files = files.concat(f);    
            });

            if ( !files.length ) {
                dispatchCallbacks('error');
                return;    
            };

            if (s.timeout)
                tTimeout = setTimeout(function(){
                    var handled = loaded.concat(errors);
                    /* search for unhandled files */
                    $.each(files, function(i, file){
                        $.inArray(file, handled) == -1 && errors.push(file);        
                    });
                    dispatchCallbacks('error');            
                }, s.timeout); 


            $.each(toLoad, function(type, urls){
                if ( $.isArray(urls) )
                    $.each( urls, function(i, url){
                        load(type, url);
                    });
                else if (typeof urls == 'string')
                    load(type, urls);
            });
            


        };

        this.js = function ( src, callback, name )
        {
        
            if ( $('script[src*="'+src+'"]').length ) {
                callback();
                return;
            };

            var script = document.createElement('script');
            script.setAttribute("type","text/javascript");
            script.setAttribute("src", src);
            script.setAttribute('id', name);

            /* Mozilla only */
               script.onerror = addError;
            
            
            if ($.browser.msie) {
               
                script.onreadystatechange = function ()    {
                     /loaded|complete/.test(script.readyState) && callback();
                     
                }
                }
            else {
                /* Mozilla, Safari, Opera, Chrome */
                script.onload = callback;
                }

            $head[0].appendChild(script);

        };
        
        this.css = function ( href, callback, name )
        {

            if ( $('link[href*="'+href+'"]').length ) {
                callback();
                return;
            };
            

            var link = $('<link rel="stylesheet" type="text/css" media="all" href="'+href+'" id="'+name+'"></link>')[0];
            if ( $.browser.msie )
                link.onreadystatechange = function () {
                    /loaded|complete/.test(link.readyState) && callback();
                }
            else if ( $.browser.opera )
                link.onload = callback;
            else
                /* Mozilla, Safari, Chrome 
                 * unfortunately it is inpossible to check if the stylesheet is really loaded or it is "HTTP/1.0 400 Bad Request"
                 * the only way to do this is to check if some special properties  were set, so there is no error callback for stylesheets -
                 * it fires alway success
                 */
                (function(){
                    try {
                        link.sheet;
                    } catch (e) {
                        cssTimeout = setTimeout(arguments.callee, 20);
                        return;
                    };
                    callback();
                })();
            $head.append(link);
        };
        
        this.img = function ( src, callback )
        {
            var img = new Image();
            img.onload = callback;
            /* working in all browsers */
            img.onerror = addError;
            img.src = src;
        };
        
        /* It works only for css */
        this.disable = function ( name )
        {    
            $('#lazy-loaded-'+name, $head[0]).attr('disabled', 'disabled');
            deleteInstance();
        };

        /* It works only for css */
        this.enable = function ( name )
        {    
            $('#lazy-loaded-'+name, $head[0]).removeAttr('disabled');
            deleteInstance();
        };
        
        /*
         * By removing js tag, script ist still living in browser memory,
         * css will be really destroyed
         */
        this.destroy = function ( name )
        {
            $('#lazy-loaded-'+name, $head[0]).remove();    
            deleteInstance();
        };
        
        function load ( type, url ) {
            
            self[type](url, function(status) { 
                status == 'error' ? errors.push(url) : loaded.push(url) && s.each(url);
                checkProgress();
            }, 'lazy-loaded-'+ (s.name ? s.name : new Date().getTime()) );
        };
        
        function dispatchCallbacks ( status ) {
            s.complete(status, loaded, errors);
            s[status]( status=='error' ? errors : loaded);
            clearTimeout(tTimeout);
            clearTimeout(cssTimeout);
            deleteInstance();
        };
        
        function checkProgress () {
            
			if (loaded.length == files.length) dispatchCallbacks('success')
            //else if (loaded.length+errors.length == files.length) dispatchCallbacks('error');
        };
        
        function addError () {
            errors.push(this.src);    
            checkProgress();
        };

    };



})(jQuery);        

