var ImageRotator = Class.create({

  initialize : function( element, imageUrls, delay, fadeDuration ) {

    this.element = $(element);
    this.images = [];
    this.delay = delay || 5;
    this.fadeDuration = fadeDuration || 1
    this.currentIndex = 0;
    this.imagesToLoad = imageUrls.size();
    this.element.setStyle( { position: 'relative' } );

    // delay can't be shorter than fade duration
    if ( this.delay <= this.fadeDuration ) { this.delay = this.fadeDuration + 0.2; }

    // Only setup the rotator if we've got more than one image to play with
    if (imageUrls.size() > 1) {

      for ( var i=0 ; src=imageUrls[i] ; i++ ) {
        this.images.push( new Element( 'img' ) );
        this.images[i].observe( 'load', this.imageLoadCallback.bind( this ) ); 
        this.images[i].src = src; // Must be set AFTER the onload event is attached!

        // Display the first image immediately (instead of waiting for the others to load)
        if ( i == 0 ) { this.element.appendChild( this.images[i] ); } 
      }

    } else if ( imageUrls.size() == 1) {
      // Just display a static image if we've only been passed 1 url
      this.element.appendChild( new Element( 'img', { src: imageUrls[0] } ) );
    } 
 
  },

  // We can only finish the setup once all of the images
  // have loaded.  If we jump too soon, we may have empty
  // size & position properties.
  imageLoadCallback : function() {

    this.imagesToLoad -= 1;

    if ( this.imagesToLoad == 0 ) {
      for ( var i=1 ; image=this.images[i] ; i++ ) {
        image.setOpacity(0);
        this.element.appendChild( image );
        image.absolutize();
        image.clonePosition( this.images.first() );
      }
      this.periodicalExecutor = new PeriodicalExecuter( this.showNextImage.bind(this), this.delay );
    } 

  },

  showNextImage : function() {
    var nextIndex = this.currentIndex == ( this.images.size() - 1 ) ? 0 : this.currentIndex + 1;
    new Effect.Opacity( this.images[this.currentIndex], { from: 1, to: 0, duration: this.fadeDuration } );
    new Effect.Opacity( this.images[nextIndex], { from: 0, to: 1, duration: this.fadeDuration } );
    this.currentIndex = nextIndex;
  }

});
