//

// CompositeLoader

//



function CompositeLoader( loaders )

{

  this.loaders    = loaders;

  this.elements   = [];

  this.incomplete = 0;

  this.pending    = false;

  this.loaded     = new Event();

}



CompositeLoader.prototype = 

{

  load: function()

  {

    var i;

    var loader;

    

    if ( !this.pending )

    {

      if ( this.loaders.length < 1 )

      {

        this.onLoaded();

      }

      else

      {

        this.pending = true;

        this.incomplete = this.loaders.length;



        for ( i = 0; i < this.loaders.length; ++i )

        {

          loader = this.loaders[ i ];

          loader.loaded.attach( this.loaderLoaded.bind( this ) );

          loader.load();

        }

      }

    }

  },

  

  getElements: function()

  {

    return this.elements;

  },

  

  loaderLoaded: function()

  {

    if ( --this.incomplete == 0 )

    {

      this.onLoaded();

    }

  },

  

  onLoaded: function()

  {

    var i, j;

    var loadedElements;

    

    for ( i = 0; i < this.loaders.length; ++i )

    {

      loadedElements = this.loaders[ i ].getElements();

      

      for ( j = 0; j < loadedElements.length; ++j )

      {

        this.elements.push( loadedElements[ j ] );

      }

    }

  

    this.pending = false;

    this.loaded.fire( this );

  }

};



//

// ImageLoader

//



function ImageLoader( url, options )

{

  this.url = url;

  this.image = null;

  this.loaded = new Event();

  this.pending = false;

  this.img = null;

  

  options = options || {};

  this.context = options.context || document;

}  



ImageLoader.prototype =

{

  load: function()

  {

    if ( !this.pending )

    {

      this.pending = true;

      

      var image = this.image = new Image();

      image.onload = this.onImageLoaded.bind( this );

      

      image.src = this.url;

    }

  },

  

  getElements: function()

  {

    return [ this.img ];

  },

  

  getElement: function()

  {

    return this.img;

  },

  

  onImageLoaded: function()

  {

    this.pending = false;

    this.createImg(); 

    this.loaded.fire( this );

  },

  

  createImg: function()

  {

    this.img = this.context.createElement( "img" );

    this.img.src = this.image.src;

    this.img.width = this.image.width;

    this.img.height = this.image.height;

  }

};



//

// MultipleImageLoader

//



function MultipleImageLoader( urls, options )

{

  this.loaded = new Event();

  this.loader = null;



  var i;

  var loaders = [];

  

  for ( i = 0; i < urls.length; ++i )

  {

    loaders.push( new ImageLoader( urls[ i ], options ) );

  }

  

  this.loader = new CompositeLoader( loaders );

  this.loader.loaded.attach( this.onCompositeLoaderLoaded.bind( this ) );

}



MultipleImageLoader.prototype =

{

  load: function()

  {

    this.loader.load();

  },

  

  getElements: function()

  {

    return this.loader.getElements();

  },

  

  onCompositeLoaderLoaded: function()

  {

    this.loaded.fire( this );

  }

};



//

// LinkedImageLoader

//



function LinkedImageLoader( imageUrl, linkUrl, options )

{

  options       = options || {};

  this.context  = options.context || document;

  this.pending  = false;

  this.loaded   = new Event();

  this.linkUrl  = linkUrl;

  

  this.imageLoader = new ImageLoader( imageUrl, options );

  this.imageLoader.loaded.attach( this.onImageLoaderLoaded.bind( this ) );

}



LinkedImageLoader.prototype =

{

  load: function()

  {

    this.imageLoader.load();

  },

  

  onImageLoaderLoaded: function()

  {

    this.createElement();

    this.loaded.fire( this );

  },

  

  getElements: function()

  {

    return [ this.element ];

  },

  

  getElement: function()

  {

    return this.element;

  },

  

  createElement: function()

  {

    var img = this.imageLoader.getElement();



    var div = this.context.createElement( "div" );

    div.style.width = new Length( img.width ).toString();

    div.style.height = new Length( img.height ).toString();



    var a = this.context.createElement( "a" );

    a.href = this.linkUrl;

    

    a.appendChild( img );

    div.appendChild( a );

    

    this.element = div;

  }

};



//

// MultipleLinkedImageLoader

//



function MultipleLinkedImageLoader( imageUrls, linkUrls, options )

{

  this.loaded = new Event();

  this.loader = null;



  var i;

  var loaders = [];

  

  for ( i = 0; i < imageUrls.length; ++i )

  {

    loaders.push( new LinkedImageLoader( imageUrls[ i ], linkUrls[ i ], options ) );

  }

  

  this.loader = new CompositeLoader( loaders );

  this.loader.loaded.attach( this.onCompositeLoaderLoaded.bind( this ) );

}



MultipleLinkedImageLoader.prototype =

{

  load: function()

  {

    this.loader.load();

  },

  

  getElements: function()

  {

    return this.loader.getElements();

  },

  

  onCompositeLoaderLoaded: function()

  {

    this.loaded.fire( this );

  }

};