(function($) {

	/**
	 * Motionlab Universal Slideshow (for products and categories)
	 * @author Joe Critchley, Motionlab
	 * @date 2010-03-01
	 */

	$.fn.ml_slideshow = function(options) {
	
		var defaults = {
			autoThumbs: false,
			noHover: false,
			thumbItems: '.products > li.grid_6',
			loadClass: 'slideshow-enabled',
			thumbsClass: 'thumbs',
			slideshowClass: 'slideshow',
			disabled: 'disabled',
			itemWidth: 710,
			prev: 'prev',
			easing: 'easeOutQuad',
			next: 'next',
			duration: 500,
			currentThumb: 'current',
			onMove: function(){},
			onInit: function(){}
		};
		
		options = $.extend(defaults, options);
		
		return this.each(function() {
		
			/**
			 * Selectors
			 */
			var $obj = $(this),
				$slideshow = $('.' + options.slideshowClass, $obj),
				$innerSlideshow = $('ul', $slideshow),
				$images = $('li', $innerSlideshow),
				$prev = $('.'+options.prev, $obj),
				$next = $('.'+options.next, $obj),
				$thumbs = null,
				$thumbItems = (options.autoThumbs === true) ? null : $(options.thumbItems),
				$currentImage = null;
					
			/**
			 * Dynamics
			 */
			var animating = false,
				currentOffset = 0,
				totalItems = $images.length,
				currentIndex = 0,
				locked = false,
				timeout = null;
						
			/**
			 * init()
			 * Initial function to get things set-up.
			 * @return void
			 */		
			function init() {
			
				// Bind the events.	
				$prev.bind('click', prev);
				$next.bind('click', next);
	
				// Disabled the prev button
				disable($prev);
				 
				// Set the current image.
				$currentImage = $images.filter(':first');
				 				
				// Put the "[rel]" attributes into the selectors' data()
				$images.each(function(i) {
					var $__image = $(this);
					var $__a = $('a[rel]', $__image);	
					if($__a.length) {
						var __data = $.parseJSON($__a.attr('rel'));
						$.each(__data, function(j, x) {
							$__image.data(j, x);	
						});
					}				
				});
				
				// Automatic thumbnails, anyone?
				if(!$thumbItems) {		
					auto_thumbs();	
					$('a', $images).click(function() { return false; }); // @todo This might be a zoom image at some point.
				}
				
				// Bind it and start it.
				$innerSlideshow.bind('slide', slide).trigger('slide');
				
				// A bit of PE for "slideshow enabled" class
				$slideshow.addClass(options.loadClass);
				
				options.onInit.call(this, [{'currentImage': $currentImage, 'currentIndex': currentIndex, 'innerSlideshow': $innerSlideshow}]);
					
			}
			 			 		
			/**
			 * slide()
			 * Skip to a certain image.
			 * @return Boolean false
			 */		
			function slide(event, index) {
								
				// Calculate new offset
				index = index || 0;
				var __newOffset = 0;
				var __newImage;
				
				$images.each(function(i) {
					if(i == index) {
						__newImage = $(this);
						return false;
					}
					else {
						__newOffset += $(this).width();	
					}
				});
				
				if(animating == true) return false;
											
				// Make the move.
				var __currentPos = parseInt($innerSlideshow.css('left'));
				animating = true;
				$innerSlideshow.animate(
					{'left': -__newOffset.toString()},
					options.duration,
					options.easing,
					function() {		
						animating = false; // Animation is complete.
					}
				);		
								
				// So the new image now becomes the current image.
				currentOffset = __newOffset;
				$currentImage = __newImage;
				currentIndex = $images.index($currentImage);
				
				// The thumbnail will need some treatment, too.
				$thumbItems.removeClass(options.currentThumb);
				$thumbItems.each(function(i) {
					if(i == currentIndex) {
						$(this).addClass(options.currentThumb);
					}
				});
								
				// Some other stuff might need to happen on the move too.					
				options.onMove.call(this, [{'currentImage': $currentImage, 'currentIndex': currentIndex}]);
				
				check_enabled();
	
				return false; // Prevent default and stop bubbling already!
				
			}
			
			/**
			 * prev()
			 * Go to the previous image if available.
			 * @return Boolean false
			 */		
			function prev(event) {
				if(currentIndex > 0) {
					$innerSlideshow.trigger('slide', [(currentIndex-1)]);
				}
				return false;
			}
			
			/**
			 * next()
			 * Go to the next image if available.
			 * @return Boolean false
			 */	
			function next(event) {
				if((currentIndex + 1) < totalItems) {
					$innerSlideshow.trigger('slide', [(currentIndex+1)]);
				}
				return false;
			}

			/**
			 * auto_thumbs()
			 * This will create some on-the-fly thumbnails next to the image.
			 * @return void
			 */	
			function auto_thumbs() {
			
				// Append an empty list.
				$thumbs = $('<ul class="' + options.thumbsClass + '"></ul>').appendTo($obj); 
				
				// Populate the thumbnail list.
				$images.each(function(i) {
					var __image = this;
					var $__thumb = $('<li class="thumb'+i+'"><img src="' + $(this).data('thumb') + '" alt="' + $(this).data('title') + '" /></li>')
						.bind('click', function(event) { $innerSlideshow.trigger('slide', [$images.index(__image)]); return false; })		
						.appendTo($thumbs);
				});
				
				$thumbItems = $('li', $thumbs);
				
				if(!defaults.noHover){
					$thumbs.hover(expand_thumbs, collapse_thumbs);
				}
				
			}
			
			/**
			 * expand_thumbs()
			 * This opens up the thumbnails box.
			 * @return void
			 */		
			function expand_thumbs(event) {
			
				timeout = setTimeout(function() {
			
					$thumbItems.stop(true)
					.animate({'width': '150px'}, 100)
					.delay(10)
					.animate({'height': '80px'}, 100, function() {
					
						$('img', this).fadeIn(500);
						
					});
		
				}, 200);
	
				return false;
	
			}
			
			/**
			 * collapse_thumbs()
			 * This opens up the thumbnails box.
			 * @return void
			 */		
			function collapse_thumbs(event) {
				
				clearTimeout(timeout);
				
				$thumbItems.stop(true)
				.animate({'height': '10px'}, 100)
				.delay(10)
				.animate({'width': '10px'}, 100, function() {
					
					$('img', this).fadeOut(500);
				
				});
				
				return false;
				
			}
						
			/**
			 * check_enabled()
			 * Checks whether the buttons should be enabled or disabled
			 * @return void
			 */	
			 function check_enabled() {
			 
			 	if(currentIndex == 0) {
					disable($prev);
				}
				else {
					enable($prev);
				}
								
				if((currentIndex+1) == totalItems) {
					disable($next);
				}
				else {
					enable($next);
				}
			 
			 }


			/**
			 * enable()
			 * Enables a button
			 * @return void
			 */	
			function enable($btn) {
				
				if($btn.hasClass(options.disabled)) {
					$btn.removeClass(options.disabled);
				}
				
			}
			
			/**
			 * disable()
			 * Disables a button
			 * @return void
			 */
			function disable($btn) {
				
				if(!$btn.hasClass(options.disabled)) {
					$btn.addClass(options.disabled);
				}
				
			}

			init();
		
		});
			
	};

})(jQuery);