/*
 * CardtasticSlideshow
 * 
 * A simple image-fading slideshow.
 *
 * (c) 2005 Tim Brayshaw <tim@twisty.com>
 *
 * Requires:
 *     Prototype <http://prototype.conio.net/>
 *     Scriptaculous <http://script.aculo.us/>
 */

var CardtasticSlideshow = Class.create();

CardtasticSlideshow.prototype =
{
	slides: new Array(),
	slideIndex: 0,
	intervalActionsIndex: 0,
	intervalActions: new Array (),
	intervalId: 0,
	debug: false,
	
	/*
	 * Initialize.
	 */
	initialize: function ()
	{
		this.createIntervalActions(5);
		this.createTransitionContainer();
		CardtasticCompatability.addEvent(window, 'resize', this.positionTransitionContainer, false);
		CardtasticCompatability.addEvent(this.getBaseImage(), 'click', this.gotoSlide.bind(this), false);
		// Internet explorer needs the event on the transition image too
		CardtasticCompatability.addEvent(this.getTransitionImage(), 'click', this.gotoSlide.bind(this), false);
	},

	/*
	 * Starts the slideshow (from the beginning).
	 */
	start: function ()
	{
		if (this.slides.length > 0)
		{
			this.intervalActionsIndex = 0;
			this.slideIndex = 0;
			this.intervalId = setInterval (this.dispatchAction.bind(this), 5 * 1000);
			this.setSlideCursor();
			return (1);
		}
		else
		{
			return (0);
		}
	},
	
	/*
	 * Stops the slideshow.
	 */
	stop: function ()
	{
		clearInterval (this.intervalId);
	},
	
	/*
	 * Add a new slide to the end of the slide stack.
	 */
	addSlide: function (mySrc, myAlt, myHref)
	{
		newSlide = {src: mySrc, alt: myAlt, href: myHref};
		this.slides.push (newSlide);
		cache = new Image();
		cache.src = newSlide.src;
	},

	/*
	 * These are like a playlist of actions to run-through to reveal a new image
	 */
	createIntervalActions: function (slideDelay)
	{
		var hiddenDelay = 0.1;
		this.intervalActions.push ({action: 'hideTransitionContainer', interval: hiddenDelay});
		this.intervalActions.push ({action: 'switchTransitionImage',   interval: hiddenDelay});
		this.intervalActions.push ({action: 'showTransitionContainer', interval: hiddenDelay});
		this.intervalActions.push ({action: 'switchBaseImage',         interval: hiddenDelay});
		this.intervalActions.push ({action: 'doTransition',            interval: slideDelay - (4 * hiddenDelay)});
	},

	/*
	 * Clones the base image,
	 * give it a new ID,
	 * hide it,
	 * adds to to the document,
	 * position it.
	 */
	createTransitionContainer: function ()
	{
		transitionImageContainer = $('baseImageContainer').cloneNode(true);
		transitionImageContainer.setAttribute('id', 'transitionImageContainer');
		Element.hide(transitionImageContainer);
		$('transition').appendChild(transitionImageContainer);
		this.positionTransitionContainer ();
	},

	/*
	 * Positions the transition image container over the base image.
	 */
	positionTransitionContainer: function ()
	{
		Position.absolutize('transitionImageContainer');
		Position.clone('baseImageContainer', 'transitionImageContainer');
	},
	
	/*
	 * Hides the transition image container.
	 */
	hideTransitionContainer: function ()
	{
		Element.hide('transitionImageContainer');
	},
	
	/*
	 * Makes the transition image container visible.
	 */
	showTransitionContainer: function ()
	{
		Element.setOpacity('transitionImageContainer', 1.0);
		Element.show('transitionImageContainer');
	},
	
	/*
	 * Switches the transition image.
	 */
	switchTransitionImage: function ()
	{
		this.getTransitionImage().src = this.getCurrentSlide().src;
	},
	
	/*
	 * Switches the base image.
	 */
	switchBaseImage: function ()
	{
		this.slideIndex < (this.slides.length - 1) ? this.slideIndex++ : this.slideIndex = 0;
		baseImage = this.getBaseImage();
		currentSlide = this.getCurrentSlide();
		baseImage.src = currentSlide.src;
		baseImage.alt = currentSlide.alt;
		this.setSlideCursor();
	},
	
	/*
	 * Navigate to href for current slide
	 */
	setSlideCursor: function ()
	{
		slide = this.getCurrentSlide();
		baseImage = this.getBaseImage();
		Element.setStyle(baseImage, {cursor: (slide.href) ? 'pointer' : 'default'});
	},

	/*
	 * Navigate to href for current slide
	 */
	gotoSlide: function ()
	{
		slide = this.getCurrentSlide();
		if (slide.href)
		{
			this.stop();
			document.location = slide.href;
		}
	},

	/*
	 * Returns the current slide
	 */
	getCurrentSlide: function ()
	{
		return (this.slides[this.slideIndex]);
	},
	
	/*
	 * Returns a reference to the base slide image
	 */
	getBaseImage: function ()
	{
		return ($('baseImageContainer').getElementsByTagName('img')[0]);
	},

	/*
	 * Returns a reference to the transition slide image
	 */
	getTransitionImage: function ()
	{
		return ($('transitionImageContainer').getElementsByTagName('img')[0]);
	},

	/*
	 * Perfom a http://script.aculo.us/ transition.
	 */
	doTransition: function ()
	{
		Effect.Fade('transitionImageContainer'); // Fade, Fold, Puff
	},
	
	/*
	 * To prevent flickers while swaping images (in IE), I've split the image swaps over a few notional 'frames'
	 * this function takes care of running through the frames sequence. A bit like a playlist.
	 */
	dispatchAction: function ()
	{
		clearInterval (this.intervalId);
		thisAction = this.intervalActions[this.intervalActionsIndex];
		this.console (thisAction.action + " : " + thisAction.interval);
		eval ('this.' + thisAction.action + '()');
		this.intervalId = setInterval (this.dispatchAction.bind(this), thisAction.interval * 1000);
		this.intervalActionsIndex < (this.intervalActions.length - 1) ? this.intervalActionsIndex++ : this.intervalActionsIndex = 0;
	},

	/*
	 * Output to a console element.
	 */
	console: function (msg)
	{
		if (this.debug == true)
		{
			$('console').innerHTML = msg;
		}
	}

}
