(function($) {

	/**
	 * Joe's magic carousel
	 * @author Joe Critchley 
	 * @date 2010-02-25
	 */

	$.fn.carousel = function(options) {
	
		var defaults = {
			size: 3,						// The number of items visible
			extraSpace: 60,					// The extra space between the number of items and carousel edges
			duration: 500,					// The length (ms) of animation when moving items
			disabled: 'disabled',			// Disabled (class name)
			prev: 'prev_arrow',				// Previous arrow (class name)
			next: 'next_arrow',				// Next arrow (class name)
			innerCarousel: '#carousel',		// Inner carousel (selector),
			loadClass: 'carousel-enabled'	// Loading class, progressive.
		};
		
		options = $.extend(defaults, options);
		
		return this.each(function() {
		
			/**
			 * Selector caching
			 */
			
			var $obj = $(this),
				$inner = $(options.innerCarousel, $obj)
				$ul = $('ul', $inner),
				$li = $('li', $ul),
				$prev = $('.'+options.prev, $obj),
				$next = $('.'+options.next, $obj);
								
			/**
			 * Dynamics
			 */
			
			var totalItems = $li.length,	// The total number of items is calculated by the length property.
				currentPosition = 0;		// The current position of the carousel, based on the first visible item
		
			/**
			 * Init
			 */
		
			// Enable the carousel
			$obj.addClass(options.loadClass);
		
			// Shift into initial position.
			$ul.css('left', options.extraSpace+'px');
			
			// Bind the events.	
			$prev.bind('click', {difference: $li.eq(0).outerWidth(true)}, move);
			
			$next.bind('click', {difference: - $li.eq(0).outerWidth(true)}, move);
			
			// Disabled the previous arrow to begin with.
			disable($prev);
									
			/**
			 * move()
			 * This is a generic event to move the carousel in any direction
			 * @return Boolean false
			 */			
			function move(event) {
				
				if($(this).hasClass(options.disabled) || $ul.is(':animated')) return false;
				
				// Which direction?	
				var __difference = event.data.difference;
				var __direction = (__difference > 0) ? -1 : +1;
							
				// Make the move.
				var __currentPos = parseInt($ul.css('left'));
				var __newPos = __currentPos + __difference;
				$ul.animate({
					'left': __newPos.toString()
				}, {
					duration: options.duration
				});		
				
				// Keep track of the current position.	
				currentPosition += __direction;
								
				check_enabled();				
							
				return false;
							
			}
			
			/**
			 * check_enabled()
			 * Checks whether the buttons should be enabled or disabled
			 * @return void
			 */	
			 function check_enabled() {
			 
			 	if(currentPosition == 0) {
					disable($prev);
				}
				else {
					enable($prev);
				}
				
				if((currentPosition + options.size) == 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);
				}
				
			}	
		
		});
			
	};

})(jQuery);
