/**
 * slideshow class!
 * 
 * @param Object	options - customize your slideshow
 * @option Number	fadeTime - the time in milliseconds in between 2 pics
 * @option Number	fadeSpeed - the time in milliseconds for the fade animation (or one of these pre-defined values: 'fast', 'normal', 'slow')
 * @option Object	hookPrevious - JQuery object to hook to 'previous'
 * @option Object	hookNext - JQuery object to hook to 'next'
 * @option Array	images - array of paths to images for slideshow
 * @option Array	links - array of urls for the visible image to link to in case of click
 * @option boolean	random - show images in random order
 * 
 * @author Matthias Mullie <matthias@netlash.com>
 */

jQuery.extend(jQuery.fn,
{
	slideshow: function (options)
	{
		return this.each(function()
		{
			// create object
			var slideshow =
			{
				/**
				 * slideshow variables
				 */
				defaults:
				{
					fadeTime : 5000,
					fadeSpeed : 'normal',
					hookPrevious : null,
					hookNext : null,
					images : new Array(),
					links : new Array(),
					random : false
				},

				element : null,
				elementNext : null,
				elementCurr : null,
				imagesArray : new Array(),
				currentImage : -1,
				timer : 0,

				/**
				 * fade images in/out
				 */
				fade : function()
				{
					// random?
					if (slideshow.options.random && slideshow.imagesArray.length > 1)
					{
						// first run? get first image instead of random image (to prevent fast flickering of the original image to the one the slideshow starts with)
						if (slideshow.currentImage == -1) slideshow.currentImage = 0;
						else
						{
							// do not pick the same image as the one currently shown
							do var random = Math.floor(Math.random() * slideshow.imagesArray.length);
							while (random == slideshow.currentImage);
							slideshow.currentImage = random;
						}
					}
					// not random, go to next (or previous) image
					else
					{
						if (arguments.length == 0 || arguments[0] == true)	slideshow.currentImage++;
						else												slideshow.currentImage--;
					}

					// boundaries doublecheck
					if (slideshow.currentImage > slideshow.imagesArray.length - 1)	slideshow.currentImage = 0;
					else if (slideshow.currentImage < 0)							slideshow.currentImage = slideshow.imagesArray.length - 1;

					if (slideshow.imagesArray[slideshow.currentImage])
					{
						if (slideshow.imagesArray[slideshow.currentImage].complete)
						{
							// prepare new image in the back
							slideshow.elementNext.attr('src', slideshow.options.images[slideshow.currentImage]);

							// fade out current img & move new image to the front and make that img visible again
							slideshow.elementCurr.fadeOut(slideshow.options.fadeSpeed, function()
							{
								slideshow.elementCurr.attr('src', slideshow.elementNext.attr('src'));
								setTimeout(function() { slideshow.elementCurr.show(); }, 50); // timeout makes sure the slow IE6 js engine can keep up :)

								// unbind possible bound click event (can't keep adding click event handlers, do we? :) )
								slideshow.elementCurr.unbind('click');

								// check if we have a link for this image
								if (slideshow.options.links[slideshow.currentImage])
								{
									slideshow.elementCurr.css('cursor', 'pointer');
									slideshow.elementCurr.click(function() { window.location = slideshow.options.links[slideshow.currentImage]; return false; }); // make sure we unbind this
								}
								else slideshow.elementCurr.css('cursor', 'default');
							});

							// let's have our next image in <fadeTime>
							slideshow.timer = setTimeout(slideshow.fade, slideshow.options.fadeTime);
						}

						// img not yet loaded, try again in 100ms
						else setTimeout(slideshow.fade, 100);
					}
				},

				/**
				 * initialise slideshow
				 */
				init : function(options)
				{
					slideshow.options = jQuery.extend({}, slideshow.defaults, options);
					slideshow.element = this;

					// images not passed along as parameter?
					if (slideshow.options.images.length == 0)
					{
						// get images (paths are comma-seperated in the rel-attribute)
						slideshow.options.images = slideshow.element.attr('rel').replace(/\s+/, '').split(',');

						// get links (if present), these are appended after each image path, preceded by a semi-colon
						for (var i = 0; i < slideshow.options.images.length; i++)
						{
							if (slideshow.options.images[i].indexOf(':') != -1)
							{
								var split = slideshow.options.images.split(':');
								slideshow.options.images[i] = split[0];
								slideshow.options.links[i] = split[1];
							}
						}

						// we don't need this anymore
						slideshow.element.attr('rel', '');
					}

					// check if src was in rel/images array (cause we will want that one too!)
					if (jQuery.inArray(slideshow.element.attr('src'), slideshow.options.images)) slideshow.options.images.push(slideshow.element.attr('src'));

					// preload images
					slideshow.preload();

					// create 2 more images so make smooth transitions :)
					slideshow.elementNext = slideshow.element.clone().insertAfter(slideshow.element);
					slideshow.elementCurr = slideshow.element.clone().insertAfter(slideshow.element).css('z-index', '1');

					// set the positions of the 2 newly created images
					slideshow.setPosition();

					// now make the original img invisible (not display none, we still need that space)
					slideshow.element.css('visibility', 'hidden');

					// when resizing, calculate position again!
					$(window).resize(slideshow.setPosition);

					// and when the document has fully loaded, calculate again!
					$('body').ready(slideshow.setPosition);

					// let the show begin
					slideshow.fade();

					// hook previous & next
					if (slideshow.options.hookPrevious)	slideshow.options.hookPrevious.click(function() { slideshow.manual(false); return false; });
					if (slideshow.options.hookNext)		slideshow.options.hookNext.click(function() { slideshow.manual(true); return false; });
				},

				/**
				 * previous & next image (previous = false, next = true)
				 */
				manual : function(next)
				{
					// stop current timer
					clearTimeout(slideshow.timer);

					// move on to next img
					slideshow.fade(next);
				},

				/**
				 * preload images
				 */
				preload : function()
				{
					// if this is possible in the current browser
					if (document.images)
					{
						for (var i = 0; i < slideshow.options.images.length; i++)
						{
							slideshow.imagesArray[i] = new Image();
							slideshow.imagesArray[i].src = slideshow.options.images[i];
						}
					}
				},

				/**
				 * set position of slideshow
				 */
				setPosition : function()
				{
					// place 'em on the correct position (right on top of the original image)
					var position = slideshow.element.position();
					slideshow.elementNext.css('position', 'absolute').css('left', position.left).css('top', position.top);
					slideshow.elementCurr.css('position', 'absolute').css('left', position.left).css('top', position.top);
				}
			};

			// init slideshow
			slideshow.init.call(jQuery(this), options);
		});
	}
});

