/**
 * Slideshow.js: Slideshow class for performing content transitions
 * $Id: slideshow.js,v 1.1 2010/02/04 15:08:24 seiz Exp $
 *
 * @author Garth Henson
 * @package library
 * @subpackage slideshow
 * @version 1.0
 * http://www.guahanweb.com/code/slideshow/
 */

/**
 * @var int SS_TRANSITION_TYPE_FADE Constant to represent "fading" as a transition type
 */
var SS_TRANSITION_TYPE_FADE = 0;

/**
 * @var int SS_TRANSITION_TYPE_SHUTTER Constant to represent "shutter" as a transition type
 */
var SS_TRANSITION_TYPE_SHUTTER = 1;

/**
 * @var int SS_TRANSITION_TYPE_SLIDE Constant to represent "sliding" as a transition type
 */
var SS_TRANSITION_TYPE_SLIDE = 2;

/**
 * Slideshow class constructor method
 *
 * @param string slideshowId The HTML ID of the element which is to become the slideshow container
 * @param object config Configuration object to control the behavior of the slideshow. 
 *	Options:
 *		string transition fade|slide|shutter - Defines the transition type between slides
 *		int timeout - Defines the time (in milliseconds) between transitions
 * @return Slideshow
 */
function Slideshow(slideshowId, config)
{
	// Constructor variable assignment
	this.id     = slideshowId;
	this.config = config;

	// Object variables referencing display settings
	this.container = document.getElementById(slideshowId);
	this.width     = this.container.offsetWidth;
	this.height    = this.container.offsetHeight;
	this.slides    = [];
	this.current   = 0;

	// Object variables to control rotation
	this.transition = 0;
	this.timeout    = 5000;
	this.timeoutID  = null;
	this.hover_stop = true;

	// Initialize the object by loading all div elements with class of "slide" into the slides array
	var eles   = this.container.getElementsByTagName('div');
	var regexp = new RegExp("slide");
	for (var i = 0; i < eles.length; i++)
	{
		if (regexp.test(eles[i].className))
		{
			
			$(eles[i]).hide();
			
			this.slides.push(eles[i]);
		}
	}
	
	// Prime the first slide to be displayed
	$(this.slides[0]).show();

	// Since timeout calls can reference functions but not methods, we reference the current object as a variable
	// that can then be called from within the timers. This allows us to have each slideshow control its own timer
	// from within.
	var show = this;

	/**
	 * Shows the next slide in the series. If we are on the last slide, it loops back to the first.
	 * @return void
	 */
	this.showNext = function()
	{
		var x = show.current + 1;
		if (x == show.getObjectCount())
		{
			x = 0;
		}

		show.change(x);
	}

	/**
	 * Shows the previous slide in the series. If we are on the first slide, it loops to the last.
	 * @return void
	 */
	this.showPrevious = function()
	{
		var x = show.current - 1;
		if (x < 0)
		{
			x = show.getObjectCount() - 1;
		}

		show.change(x);
	}

	/**
	 * Processes the transition from the requested slide to the slide at the requested index
	 */
	this.change = function(index)
	{
		switch (this.transition)
		{
			case SS_TRANSITION_TYPE_FADE:
				this.fade(index);
				break;

			case SS_TRANSITION_TYPE_SHUTTER:
				this.shutter(index);
				break;

			case SS_TRANSITION_TYPE_SLIDE:
				this.slide(index);
				break;
		}
	}

	/**
	 * Fades visibility from the currently visible slide to the slide at the provided index
	 * @param int index
	 * @return void
	 */
	this.fade = function(index)
	{
		var slide1 = this.slides[this.current];
		var slide2 = this.slides[index];
		
		var show = this;
		$(slide1).fadeOut('slow', function()
		{
			show.current = index;
		});

		$(slide2).fadeIn('slow');
	}

	/**
	 * Immediately transitions from the currently visible slide to the slide at the provided index
	 * @param int index
	 * @return void
	 */
	this.shutter = function(index)
	{
		var slide1 = this.slides[this.current];
		var slide2 = this.slides[index];

		$(slide1).hide();
		$(slide2).show();

		this.current = index;
	}

	/**
	 * @param int index
	 * @return void
	 */
	this.slide = function(index)
	{
		// TODO: Function to slide the slide at index into the viewable port ABOVE the currently viewable slide
	}

	/**
	 * Retrieves the number of slides currently loaded in this object
	 * @return int
	 */
	this.getObjectCount = function()
	{
		return this.slides.length;
	}

	/**
	 * Retrieves the HtmlElement of this object's container
	 * @return HtmlElement
	 */
	this.getEle = function()
	{
		return document.getElementById(this.id);
	}

	/**
	 * Sets the transition type for this object
	 * @param string type shutter|fade|slide
	 * @return void
	 */
	this.setTransitionType = function(type)
	{
		if (type == 'shutter')
		{
			this.transition = SS_TRANSITION_TYPE_SHUTTER;
		}
		else if (type == 'fade')
		{
			this.transition = SS_TRANSITION_TYPE_FADE;
		}
		else if (type == 'slide')
		{
			this.transition = SS_TRANSITION_TYPE_SLIDE;
		}
	}

	// Now that all the functions are set, take care of any provided configuration variables
	if (this.config.transition != null)
	{
		this.setTransitionType(this.config.transition);
	}

	if (this.config.timeout != null)
	{
		this.timeout = this.config.timeout;
	}

	if (this.config.hover_stop != null && this.config.hover_stop == false)
	{
		this.hover_stop = false;
	}

	if (this.hover_stop == true)
	{
		$(this.getEle()).hover(
			function()
			{
				show.stop();
			},
			function()
			{
				show.play();
			}
		);
	}
}

/**
 * Begin the slideshow animation and set the interval for rotation
 * @return void
 */
Slideshow.prototype.play = function()
{
	if (this.timout != null)
	{
		return; // Slideshow is currently active
	}

	this.timeoutID = setInterval(this.showNext, this.timeout);
}

/**
 * Stop slideshow animation by clearing the current object's interval
 * @return void
 */
Slideshow.prototype.stop = function()
{
	if (this.timeoutID)
	{
		clearInterval(this.timeoutID);
	}

	this.timeoutID = null;
}
