/**
 * jQuery-Plugin "transporter"
 * 
 * @version: 1.0, 08.25.2009
 * 
 * @author: Tyler Gaw
 *          tylerg@arc90.com
 *
 * 
 * @example: $('selector').transporter();
 * 
 */

;(function($) {
	
	var settings     = {};
	var slides       = new Array();
	var curSlide     = 0;
	var viewableArea = 0;
	var maxSlide     = 0;
	
	
	jQuery.fn.transporter = function(options) {
		settings = jQuery.extend({}, $.fn.transporter.defaults, options);
		
		jQuery(this).each(function() {
			var $this = $(this);
			prepareMarkup($this);
			
			$this.nextControl = settings.nextControl || null;
			if($this.nextControl != null)
			{
				$($this.nextControl).click(function()
				{
					if(!$(this).hasClass(settings.inactiveClass))
					{
						next($this);
					}
					return false;
				});
				
				if(maxSlide == 0)
				{
					$($this.nextControl).addClass(settings.inactiveClass);
				}
			}
			
			$this.prevControl = settings.prevControl || null;
			if($this.prevControl != null)
			{
				$($this.prevControl).click(function()
				{
					if(!$(this).hasClass(settings.inactiveClass))
					{
						prev($this);
					}
					return false;
				}).addClass(settings.inactiveClass);
			}
		});
		return jQuery;
	};


	/**
	 * Advance to the next slide(s)
	 *
	 */
	var next = function(obj)
	{	
		var remainder = remainingArea(obj);
		
		if(remainder < viewableArea)
		{
			var pos = slides[curSlide] + remainder;
			curSlide = curSlide += 1;
		}
		else
		{
			curSlide = curSlide += 1;
			var pos = slides[curSlide];
		}
		moveContainer(obj, (pos * -1));
		setControlsStatus();
	};
	
	
	/**
	 * Go to previous slide(s)
	 *
	 */
	var prev = function(obj)
	{
		curSlide = curSlide -= 1;
		var pos = slides[curSlide] * -1;
		moveContainer(obj, pos);
		setControlsStatus();
	};
	
	
	/**
	 * Detect whether we are on the first or last slide
	 * to turn the controls on/off
	 */
	var setControlsStatus = function()
	{
		
		switch (curSlide)
		{
			case 0:
				$(settings.prevControl).addClass(settings.inactiveClass);
				$(settings.nextControl).removeClass(settings.inactiveClass);
				break;
				
			case maxSlide:
				$(settings.nextControl).addClass(settings.inactiveClass);
				$(settings.prevControl).removeClass(settings.inactiveClass);
				break;
			
			default:
				$(settings.prevControl).removeClass(settings.inactiveClass);
				$(settings.nextControl).removeClass(settings.inactiveClass);
		}
	}
	
	
	/**
	 * Move the container to the selected section
	 *
	 */
	var moveContainer = function(obj, pos)
	{		
		switch(settings.animation)
		{
			case 'slide':
				obj.animate({ 
				        	left: pos
				      		}, 800);
				break;
		
			case 'fade':
				obj.animate( { opacity: 0 }, 350)
					.animate( {left: pos}, 20 )
					.animate( {opacity: 1}, 350);
				break;
			
			case 'none':
			default:
				obj.css('left', pos);
		}
	}
	
	
	/**
	 * Set some needed defaults, position the children elements
	 *
	 */
	var prepareMarkup = function(obj)
	{		
		var curSectionsWidth = 0;
		var containerWidth = obj.width();
		var sectionPadding = obj.innerWidth() - containerWidth;
		viewableArea = containerWidth - sectionPadding;
				
		obj.children(1).each(
			function(i)
			{
				$(this).css({
					'left' : curSectionsWidth
				});
				
				curSectionsWidth = curSectionsWidth + $(this).width();
				
				curLeftPos = viewableArea * i;
				slides.push(curLeftPos);
			}
		);
		
		/**
		 * We need to set the width of the content container so
		 * it is as wide as all of its child elements laid out horizontally
		 */
		obj.width(curSectionsWidth);
		
		/**
		 * This is a failsafe put in in case the slides are not as wide
		 * as the viewable area. it restricts the number of slides to 
		 * how many fit in the viewable area
		 */
		maxSlide = Math.floor(curSectionsWidth / (viewableArea + settings.widthThreshold));
	};
	
	
	/**
	 * Utility function to find the remaining portion of the slides
	 *
	 */
	var remainingArea = function(obj)
	{
		var leftPos = parseInt(obj.css('left')) * -1;
		var remainder = obj.width() - leftPos - viewableArea;
		return remainder;
	}
	
	
	/**
	 * Create defaults settings as a public object
	 * this allows users to easily overwrite defaults
	 *
	 * (e.g. $.fn.transporter.defaults.item = 'value')
	 *
	 *
	 * animation: Can be a string one of 'none', 'slide', 'fade'.
	 *
	 * NOTE: widthThreshold is crazy pants. Sometimes when your child elements
	 *       have paddings, borders, etc. Sometimes the max number of slides can 
	 *       come out wrong. widthThreshold is the amount of pixels over the viewable
	 *       width that your container has to be to register as actually "too wide"
	 *       Thus adding another slide
	 *
	 */
	jQuery.fn.transporter.defaults = {
		animation: 'slide',
		inactiveClass: 'inactive',
		widthThreshold: 20
	};

})(jQuery);
