/*******JQUERY UI IMAGE LOADER PLUGIN v1.4 ************
*
*	by alan clarke
*	created: 6 Apr 2011
*	last update: 7 May 2011
*	alan@staticvoid.info
*
*	Special hanks to the following for their comments and bugfixes:
*		Romain Sauvaire, http://www.jefaisvotresite.com
*		Frank Boers, http://sevideo.se
*
*************************************************/
(function($) {

$.widget( "ui.imageLoader", { 
    options: { 
        async: true,
        images: [ ]
    },
    total: 0,
    _init: function(){ 
        var self = this;
		var i;

        self.total++;
        //load counter
        self.loaded = 0;

        //local variable to track image attributes
        self.data = [ ];
        self.stats = {
			loaded:0,
			errored:0,
			allcomplete:false
		};

		//if images option is a selector, collect all image sources from matched elements
		if( typeof self.options.images === 'string' ) {
			var images = [ ];
			$.map( $( self.options.images ), function(el, i){
	            images.push($(el).attr('src'));
			});		
			self.options.images = images;
		}
		
        for ( i = 0; i < self.options.images.length; i++ ){ 
            self.data.push( { 
                init: false,
                complete: false,
                error: false,
                src: self.options.images[ i ],
                img: new Image(),
                i: i
            });
        }

        //controls the number of threads simmultaneously loading unloaded images
        for ( i = 0;  ( ( i < self.data.length ) && ( ( self.options.async === true || i === 0 ) || i < parseInt( self.options.async, 10 ) ) ); i++ ){ 
        
            self._loadImg( i );

        }
        return self;
    },
    _loadImg: function( i ){ 
        var self = this;
        if ( i !== false && i < self.data.length ){ 

            if ( !self.data[ i ].init ){ 
            
                //lock image
                self.data[ i ].init = true;
                
                self._trigger( "start", null, { 
                    i: i,
                    data: self.getData( )
                });

                //using setTimeout to force multiple threading and give some time for garbage collection between image loads
                setTimeout( function(){ 
										
						//error event
	                    self.data[ i ].img.onerror = function(){ 

	                        self.loaded++;
							self.stats.errored++;
	                        self.data[ i ].error = true;
	                        self._trigger( "error", null, { 
	                            i: i,
	                            data: self.getData( )
	                        });
	
	                        self._complete( i );
	                    };

	                    self.data[ i ].img.onload = function(){ 
						
							//redirect to error for when a malformed image is passed in using firefox (thanks Frank Boers)
							if(self.data[ i ].img.width < 1 ) {
								return self.data[ i ].img.onerror();
							}
						
	                        self.loaded++;
							self.stats.loaded++;
	                        self.data[ i ].complete = true;

	                        self._trigger( "complete", null, { 
	                            i: i,
	                            data: self.getData( )
	                        });

	                        self._complete( i );
	                    };
	
                    //setting the src after the onload event incase image is already cached
                    self.data[ i ].img.src = self.data[ i ].src;
                    
                    
                }, 1 );
            }
        }
    },
    _complete: function( i ){ 
        var self = this;

		
        //if thread is synchronous move on to next unloaded image
        if ( !self.options.async || typeof self.options.async === "number" ){ 
            var next = self._next( i );
            self._loadImg( next );
        }

        //if last image, trigger allcomplete event
        if ( self.loaded === self.data.length ){ 
            //triger complete
            self._trigger( "allcomplete", null, self.getData( ) );
			self.stats.allcomplete = true;
        }
    },

    //returns index of next image that isn't already loading
    _next: function( j ){ 
        var self = this;
		var i;
		
        for ( i = 0; i < self.data.length; i++ ){ 
            if ( i !== j && !self.data[ i ].init ){ 
                return i;
            }
        }
        return false;
    },
    getData: function(){ 
        return $.extend( true, [ ], this.data );
    },
    getStats: function(){ 
        return $.extend( true, [ ], this.stats );
    },
    destroy: function(){ 
        $.Widget.prototype.destroy.apply( this, arguments );
    }
 });


})(jQuery);
