/**
 * Author: Robert S. Kraig
 *
 * Description: This plugin is not really mean't to re-invent the wheel.
 * It is just a simple implementation of a carousel, the most basic features.
 * It's small enough for a single developer to figure out what is going
 * on and to improve or add features on top of the existing functionality.
 *
 * There is not doubt that this plugin can be improved. Have at it.
 * 
 */

/**
 * Logic Helper to jQuery Plugin
 * @param carousel jQuery div
 * @param config jQuery Plugin Default Parameters
 */
function carouselHelper(carousel,config)
{
	this.items		= config.scrollLength;
	this.navID		= config.navID;
	this.carousel	= carousel;

	this.scrolldist	= 0;
	this.maxwidth	= 0;

	this.prevID		= config.prevNavSelector;
	this.nextID		= config.nextNavSelector;

	this.scrollSpeed = config.scrollSpeed;

	var self = this;

	this.calculate	= function()
	{
		self.scrolldist = self.items * $('ul li',self.carousel).data().width;
		return this;
	};

	this.maxdist	= function(){
		return -$('ul',self.carousel).data().width;
	};

	this.nav_end	= function()
	{
		var currentdist = parseInt($("ul",self.carousel).css('left').replace('px',''));
		return (self.maxdist() >= (currentdist + (-self.scrolldist)));
	};

	this.nav_start	= function()
	{
		var currentdist = parseInt($("ul",self.carousel).css('left').replace('px',''));
		return (currentdist == 0);
	};

	this.init		= function(){
		var width;
		$('ul',self.carousel).data('width',0);
		$('ul li',self.carousel).each(function()
		{
			width = $(this).outerWidth(true);
			$('ul',self.carousel).data().width+=parseInt(width);
		});

		self.maxwidth = width;
		$('ul li',self.carousel).data('width',self.maxwidth);
		$('ul',self.carousel).css('width',$('ul',self.carousel).data().width+'px');
		self.calculate();
		if(self.scrolldist > $('ul',self.carousel).data().width)
		{
			$('#'+self.navID+' a')
				.removeClass('active')
				.addClass('disable');
		}
	};

	this.init();
}

function removeSelectors(value)
{
	var nav_type,navID;
	if(value.match(/^#/))
	{
		nav_type = 'id';
		navID = value.replace(/^#/,'');
	}
	else if(value.match(/^\./))
	{
		nav_type = 'class';
		navID = value.replace(/^\./,'');
	}

	return {
		selector:navID,
		type:nav_type
	};
}

(function($){

	$.fn.miniCarousel = function(settings)
	{

		var config = {
			'navID':'#miniCarousel_nav',
			'scrollLength':3,
			'buildNavigation':true,
			'scrollSpeed':'normal',
			'nextNavSelector':'.next',
			'prevNavSelector':'.prev'
		};

		if(!config.navID.match(/^(#|\.)/))
		{
			$.error('You must Define a Navigation ID/Class');
		}
		if(config.scrollLength < 1)
		{
			$.error('You must give scrollLength an value greater than 0');
		}
		if(!config.scrollSpeed.match(/^(fast|normal|slow)|[0-9]+$/))
		{
			$.error('You must Define your scrollSpeed with either a jQuery animaton Speed Alias (fast,normal,slow) or a millisecond value');
		}
		if(settings) $.extend(config, settings);


		var navigation_div = removeSelectors(config.navID);

		if(config.buildNavigation)
		{
			var navigation_btn_next = removeSelectors(config.nextNavSelector);
			var navigation_btn_prev = removeSelectors(config.prevNavSelector);

			var navigation_html = '<div '+navigation_div.type+'="'+navigation_div.selector+'">';
			switch(navigation_btn_next.type)
			{
				case 'class':
					navigation_html += '<a class="'+navigation_btn_next.selector+' active" href="#"></a>';
					break;
				case 'id':
					navigation_html += '<a id="'+navigation_btn_next.selector+'" class="active" href="#"></a>';
					break;
				default:
			}
			switch(navigation_btn_prev.type)
			{
				case 'class':
					navigation_html += '<a class="'+navigation_btn_prev.selector+' active" href="#"></a>';
					break;
				case 'id':
					navigation_html += '<a id="'+navigation_btn_prev.selector+'" class="active" href="#"></a>';
					break;
				default:
			}
			navigation_html += '</div>';
		}

		this.each(function()
		{
			if($('ul li', $(this)).length < 1)
			{
				$.error('This plugin requires atleast 1 li element to function');
			}
		});

		return this.each(function()
		{
			if(config.buildNavigation)
			{
				$(this).prepend(navigation_html);
			}


			var btns = new carouselHelper($(this),config);

			$(btns.navID + ' ' + btns.nextID).live('click',function()
			{
				var $navprev = $(btns.navID + ' ' + btns.prevID)
				var $navnext = $(btns.navID + ' ' + btns.nextID)

				if($navnext.hasClass('disable')) return false;

				if(!btns.nav_end())
				{
					$navprev
						.removeClass('disable')
						.removeClass('stop')
						.addClass('active');
				}

				if(btns.nav_end())
				{
					$navnext.addClass('stop');
					return false;
				}

				$navnext.addClass('disable');

				$("ul",btns.carousel)
					.dequeue()
					.animate(
						{
							// Notice the direction this is moving in?
							"left": "-="+btns.scrolldist+"px"
						},
						btns.scrollSpeed ,
						function()
						{
							$navnext
								.removeClass('disable')
								.removeClass('mousedown');
							if(btns.nav_end())
							{
								$navnext.trigger('click');
							}
						}
					);
				return false;
			})
			.mouseover(function(){
				$(btns.navID + ' ' + btns.nextID)
					.addClass('mouseover');
			})
			.mousedown(function(){
				$(btns.navID + ' ' + btns.nextID)
					.addClass('mousedown');
			})
			.mouseout(function(){
				$(btns.navID + ' ' + btns.nextID)
					.removeClass('mouseover')
					.removeClass('mousedown');
			});

			$(btns.navID + ' ' + btns.prevID).live('click',function()
			{
				var $navprev = $(btns.navID + ' ' + btns.prevID)
				var $navnext = $(btns.navID + ' ' + btns.nextID)

				if($navprev.hasClass('disable')) return false;

				if(!btns.nav_start())
				{
					$navnext
						.removeClass('disable')
						.removeClass('stop')
						.addClass('active');
				}

				if(btns.nav_start())
				{
					$navprev.addClass('stop');
					return false;
				}

				$navprev.addClass('disable');

				$("ul",btns.carousel)
					.dequeue()
					.animate(
						{
							// Notice the direction this is moving in?
							"left": "+="+btns.scrolldist+"px"
						},
						btns.scrollSpeed,
						function()
						{
							$navprev
								.removeClass('disable')
								.removeClass('mousedown');
							if(btns.nav_start())
							{
								$navprev.trigger('click');
							}
						}
					);

				return false;
			})
			.mouseover(function(){
				$(btns.navID + ' ' + btns.prevID)
					.addClass('mouseover');
			})
			.mousedown(function(){
				$(btns.navID + ' ' + btns.prevID)
					.addClass('mousedown');
			})
			.mouseout(function(){
				$(btns.navID + ' ' + btns.prevID)
					.removeClass('mouseover')
					.removeClass('mousedown');
			});
		});
	}
})(jQuery);
