var SlideShow = Class.create();

SlideShow.prototype =
{
  /***************************
  * Initialize the slideshow.
  ***************************/
  initialize: function(container, options, images, previousButton, pauseButton, forwardButton)
  {
    this.container = $(container);
    this.backButton = $(previousButton);
    this.pauseButton = $(pauseButton);
    this.nextButton = $(forwardButton);
    this.currentImage = 0;
		this.imageIndex = 0;
		this.images = images;
		
    this.options = Object.extend(
    {
      displayTime : 10,
      fadeDuration : 2
    },
    options || {});

		//Create a div that will hold the image fading away, and next to display
    this.divBuffer = document.createElement('div');
    this.divBuffer.id = 'divBuffer';
		Element.setStyle(this.divBuffer, 
  	{
  	  background: Element.getStyle(this.container, 'background'),
			height: Element.getStyle(this.container, 'height'),
			left: Element.getStyle(this.container, 'left'),
			position: 'absolute',
			top: Element.getStyle(this.container, 'top'),
			width: Element.getStyle(this.container, 'width'),
			zIndex: 2
		});
		this.container.appendChild(this.divBuffer);

    //Loop through the images and preload them
    for (var iImages = 0; iImages < this.images.length; iImages++)
    {
      var imgPreload = new Image();
      imgPreload.src = this.images[iImages];
    }

    //Setup event-handlers
    Event.observe(this.backButton, 'click', function()
    {
      this.forcePrevious();
    }.bind(this));
    
    Event.observe(this.nextButton, 'click', function()
    {
      this.forceNext();
    }.bind(this));

    Event.observe(this.pauseButton, 'click', function()
    {
      this.peSlideShow.stop();
    }.bind(this));

    //Setup the next image of the slide show
		this.peSlideShow = new PeriodicalExecuter(this.showNext.bind(this), this.options.displayTime);
		this.showNext();
  },
  
  /*********************************************************************
  * Forces the next image in the array to display and resets the timer.
  *********************************************************************/
  forceNext: function()
  {
    this.peSlideShow.stop();

    if (this.currentImage > this.imageIndex)
    {
      this.imageIndex = this.currentImage + 1;

  		if (this.images[this.imageIndex] == null)
	  		this.imageIndex = 0;
    }

		//Load the new image into the buffer DIV
		Element.setStyle(this.divBuffer,
		{
			background:"url('" + this.images[this.imageIndex] + "') no-repeat"
	  });

    this.showNext();
		this.peSlideShow = new PeriodicalExecuter(this.showNext.bind(this), this.options.displayTime);
  },
  
  /***************************************
  * Displays the next image in the array.
  ***************************************/
	showNext: function()
	{
	  this.currentImage = this.imageIndex;
		this.imageIndex++;
		
		if (this.images[this.imageIndex] == null)
			this.imageIndex = 0;
		
		new Effect.Appear(this.divBuffer,
		{
			duration: this.options.fadeDuration, 
			afterFinish: this.shiftImage.bind(this)
		});
	},
  
  /*************************************************************************
  * Forces the previous image in the array to display and resets the timer.
  *************************************************************************/
  forcePrevious: function()
  {
    this.peSlideShow.stop();

    if (this.currentImage < this.imageIndex)
    {
      this.imageIndex = this.currentImage - 1;

  		if (this.images[this.imageIndex] == null)
	  		this.imageIndex = this.images.length - 1;
    }

		//Load the new image into the buffer DIV
		Element.setStyle(this.divBuffer,
		{
			background:"url('" + this.images[this.imageIndex] + "') no-repeat"
	  });

    this.showPrevious();
		this.peSlideShow = new PeriodicalExecuter(this.showNext.bind(this), this.options.displayTime);
  },

	/*******************************************
	* Displays the previous image in the array.
	*******************************************/
	showPrevious: function()
	{
	  this.currentImage = this.imageIndex;
		this.imageIndex--;
		
		if (this.images[this.imageIndex] == null)
			this.imageIndex = this.images.length - 1;
		
	  new Effect.Appear(this.divBuffer,
	  {
			duration: this.options.fadeDuration, 
			afterFinish: this.shiftImage.bind(this)
	  });
	},


	/*****************************************************************************
	* Callback to handle the actual work of the 'slideshow' effect.  It swaps the
	* images between the two DIV elements.
	*****************************************************************************/
	shiftImage: function()
	{
		//Copy the image of the buffer DIV to the container DIV
		Element.setStyle(this.container,
		{
			background: Element.getStyle(this.divBuffer, 'background-image')
		});
		
		//Hide the buffer DIV element
		Element.setOpacity(this.divBuffer, 0);
		
		//Load the new image into the buffer DIV
		Element.setStyle(this.divBuffer,
		{
			background:"url('" + this.images[this.imageIndex] + "') no-repeat"
	  });
	}
}