/**
 * @author JD Medina (www.zemoga.com)
 * @date Jan 28th 2010 
 * All Functionality related with the Carousel Component for Vertical Pages
 * @ js observer: js_vert_carousel
 * @ options: js_four_up (skips 4 items at a time)
 * @ options: js_infinite (infinite looped)
 * @ options: js_focus (fits only odd items and focuses the center item while dimming the rest)
 * @ options: js_offset (to be used with js_focus: it offsets the carousel so the first <li> is the one in focus)
 * @example 
 * 		<div class="your_class js_vert_carousel js_infinite"> 
 *			<!-- NO Extra content may go here except when the carousel is a four_up -->
 *			<div id="catCarousel"> 																			-> position: relative, overflow: hidden
 *				<ul id="catItems"> 																				-> position: absolute, left: 0, width: 9000px	
 *					<li><a href="#"><img src="/img/image.jpg" /></a></li> 	-> float: left, text-align: center
 *					<li><a href="#"><img src="/img/image.jpg" /></a></li> 	
 *					<li><a href="#"><img src="/img/image.jpg" /></a></li> 	
 *				</ul>
 *				<a class="button prev" id="cat_Previous">Previous</a>
 *		   	<a class="button next" id="cat_Next">Next</a>
 *			</div>
 *			<!-- Extra content may go here -->
 *		</div>
 * 
 */ 
 
$(function() {

	//JS observer
	
	var carouselObserver = $(".js_vert_carousel");
	
	//TO DO: Make the carousel object fetch the observer?
	var relatedLinksObserver = $(".js_related_links");
	
	var carousel, related;
	
	$(carouselObserver).each(function(){
		
		var self = this;
		
 		carousel = new VerticalCarousel($(self));
 		
 		if( carousel.getFocusedItem() ) {
 			//related = new RelatedLinks(relatedLinksObserver, carousel.getFocusedItem());
 		}
 		
 		carousel.onClickedBtn = function() {
		//	related.setFocusedItem(this.getFocusedItem());
		};
 				
	});

});

function VerticalCarousel(element) {

	var self = this;

	//Public properties

	this.car = $(element);
	this.onClickedBtn = null;
	
	//Private properties
	
	var scrollSpeed = 1000;
	var counter = 1;
	var option = option();
	var focus = $(self.car).hasClass("js_focus");
	var infinite = $(self.car).hasClass("js_infinite");
	var liWidth = $(self.car).find("ul li").width();
	var items = $(self.car).find("ul li").length;
	var carPosition = parseInt($(self.car).find("ul").css("left"));
	var focusOffset = $(self.car).hasClass("js_offset");
	var focusedItem = setFocus();
	var nextBtn;
	var prevBtn;
	var placeHolderWidth = $(self.car).find("ul").parent().width();
	var visibleItems = Math.floor(placeHolderWidth / liWidth);
	
	//Start the set-up
	
	setUp();
	
	//Window resize
	
	$(window).resize(function() {
		if( option != 4 ) {		
			calibrate();
		}
		else {
			visibleItems = option;
		}
	});
	
	
	
	// ** Carousel  Public Methods ** //
	
	this.getFocusedItem = function () { 
		return focusedItem;
	};
	
	// ** Carousel  Private Methods ** //
	
	function option() {
		if( $(self.car).hasClass("js_four_up") ) {
			return 4;
		}
		else if ( $(self.car).hasClass("js_visible_jump") ) {
			return visibleItems;
		}
		else {
			return 1;
		}
	};
	
	function setUp() {
	
		//Pre set-up: CSS properties needed for the carousel to work
		
		var carUl = $(self.car).find("ul");
		
		$(carUl).parent().css({
			"overflow"		:		"hidden",
			"position"		:		"relative"
		});
		
		$(carUl).css({
			"left"				:		0,
			"position"		:		"absolute",
			"width"				:		9000
		});
		
		$(carUl).find("li").css({
			"float"				:		"left",
			"textAlign"		:		"center"
		});
		
		//Set-up
	
		nextBtn = $(self.car).find(".next");
		prevBtn = $(self.car).find(".prev");
		
		$(nextBtn).bind("click", function(e) {
			nextItem();
			e.preventDefault();
		});
		
		$(prevBtn).bind("click", function(e) {
			prevItem();
			e.preventDefault();
		});
		
		//Four up
		
		if(option != 4) {
			calibrate();
		}
		else {
			visibleItems = option;
		}
		
		//Infinite
		
		if( !infinite ) {
			disableObj(prevBtn, true);
		}
		
		//Offset for first <li> to be focused
		
		if ( focusOffset ) {
			if ( visibleItems > 1 ) {
				cloneItems("offset");
				setFocus();
			}
			else {
				//Position adjustment
				$(self.car).find("ul").css({"left"	:	0});
				counter = 1;
				carPosition = 0;
			}
		}
		
	};
	
	function itemWidth() {
		return $(self.car).find("ul li").width();
	};
	
	function enableObj(btn, fade, func) {
		if ( func ) {
			$(btn).bind("click", function(e){
				func();
				e.preventDefault();
			});
		}
		if( fade ) {
		//	$(btn).fadeTo("fast", 1);
			$(btn).addClass("selected");
		}
	};

	function disableObj(btn, fade, unb) {
		if ( fade ) {	
			//$(btn).fadeTo("fast", 0.4);
			$(btn).removeClass("selected");
		}
		if ( unb ) {
			$(btn).unbind("click");
		}
	};
	
	function checkVisibleItems() {
		//Check if the items are less than the visible items, if so: hide the arrows
		
		if(items <= visibleItems) {
			visibleItems = items;
			
			$(nextBtn).hide();
			$(prevBtn).hide();		
		}
		else if(infinite) {
			$(nextBtn).show();
			$(prevBtn).show();
		}
	};
	
	function calibrate() {
		var minGap = 5;
		var tolerance = 2;
		var adjPos = 0;
		var placeHolderWidth = $(self.car).find("ul").parent().width();
		visibleItems = Math.floor(placeHolderWidth / liWidth);
		
		checkVisibleItems();
		
		var availableSpace = Math.round(placeHolderWidth/visibleItems);
		
		var increment = availableSpace - liWidth;
		
		//Check if the increment is less than the minimum gap
		
		if(increment < minGap) {
			increment = minGap;
		}
		
		//Check if the combined width of the list items plus the increment exceeds the container width, if so: reduce the number of items
		
		var combinedItemWidth = ( liWidth + increment )*visibleItems;
		
		if (placeHolderWidth + tolerance < combinedItemWidth) {
			visibleItems--;
			availableSpace = Math.ceil(placeHolderWidth/visibleItems);
			increment = availableSpace - liWidth;
		}
		
		//If focus feature and visible items is even, reduce the number of items
		
		if( focus ) {
		
			if( visibleItems%2 == 0 ) {
		
				visibleItems--;
				availableSpace = Math.ceil(placeHolderWidth/visibleItems);
				increment = availableSpace - liWidth;
			
			}
			
			setFocus();
		}
		
		checkVisibleItems();
		
		//Assign the increment
		
		var curLiWidth = liWidth + increment;
	
		$(self.car).find("ul li").each(function() {
			$(this).width( curLiWidth );
		});
		
		// UL position adjustment after window resize

		
		if (visibleItems == 1) {
			adjPos = curLiWidth*(counter);
		}
		else {
			adjPos = curLiWidth*(counter-1);
		}
		
		$(self.car).find("ul").css({"left"	:	-adjPos});
		
		carPosition = -adjPos;
		
		/** 	TO DO: 	
		*			Figure out what to do when: 
		*			If the carousel is on the last position and the max visible items increases, there would be a gap to the right of the last item
		**/
	};
	
	function setFocus() {
	
	var placeHolderWidth = $(self.car).find("ul").parent().width();
		
		if(focus) {
		
			var centerItem = Math.floor( visibleItems/2 ) + counter - 1;
		
			if( visibleItems%2 == 1 && visibleItems > 1 ) {
				disableObj($(self.car).find("ul li:lt("+centerItem+")"), true);
				disableObj($(self.car).find("ul li:gt("+centerItem+")"), true);
				
				$(self.car).find("ul li:lt("+centerItem+") .newArrivalText").fadeOut();
				$(self.car).find("ul li:gt("+centerItem+") .newArrivalText").fadeOut();
				
				enableObj($(self.car).find("ul li").eq(centerItem), true);
				
				$(self.car).find("ul li").find(".newArrivalText").eq(centerItem).fadeIn();
			}
			else if(visibleItems <= 2) {
				enableObj($(self.car).find("ul li"), true);
				$(self.car).find("ul li").find(".newArrivalText").fadeIn();
			}
			
			focusedItem = $(self.car).find("ul li").eq(centerItem);
			
			if( self.onClickedBtn ){
				self.onClickedBtn();
			}
			
			return focusedItem;
						
		}
	};
	
	function nextItem() {
		var curLiWidth = itemWidth();
		carPosition = Math.abs(carPosition);
		var multiplier = option;
		var placeHolderWidth = $(self.car).find("ul").parent().width();
		
		//Cloning feature for the infinite carousel
		
		if ( counter + visibleItems > items && infinite ) {

			cloneItems("end");
		
		}
				
		if( counter + visibleItems <= items ) {
			carPosition += curLiWidth*multiplier;
			
			//Unbind click to prevent multiple clicks
			
			disableObj(nextBtn, false, true);
		
			$(self.car).find("ul").animate({
				"left"	:		-carPosition
			}, scrollSpeed, function(){
				enableObj(nextBtn, false, function() { nextItem() });
			});
			
			enableObj(prevBtn, true);
				
			counter += multiplier;
			
			setFocus();
		}
		
		if ( counter + visibleItems > items && !infinite ){
			disableObj(nextBtn, true);
		}
		
		carPosition = -carPosition;

	};
	
	function prevItem() {
		var curLiWidth = itemWidth();
		var multiplier = option;
		var placeHolderWidth = $(self.car).find("ul").parent().width();
		carPosition = parseInt($(self.car).find("ul").css("left"));

		//Cloning feature for the infinite carousel
		
		if ( counter == 1 && infinite) {
			
			cloneItems("start");
	
		}
		
		if( counter > 1 ) {
			carPosition += curLiWidth*multiplier;
			
			//Unbind click to prevent multiple clicks
			
			disableObj(prevBtn, false, true);
		
			$(self.car).find("ul").animate({
				"left"	:		carPosition
			}, scrollSpeed, function(){
				enableObj(prevBtn, false, function() { prevItem() });
			});
			
			enableObj(nextBtn, true);
			
			counter -= multiplier;
			
			setFocus();
		}
		
		if( counter == 1 && !infinite ) {
			disableObj(prevBtn, true);
		}
		
	};
	
	function cloneItems(cloneWhere) {
		switch(cloneWhere) {
			case "start":
				var cutOff = visibleItems-1;
				var clones = $(self.car).find("ul li:gt("+cutOff+")");
				$(clones).clone().insertBefore( $(self.car).find("ul li:first-child") );
				$(self.car).find("ul li:gt("+(cutOff + clones.length)+")").remove();
				
				//Position adjustment
				var curLiWidth = itemWidth();
				var adjPos = curLiWidth*(items - visibleItems);
				$(self.car).find("ul").css({"left"	:	-adjPos});
				counter = items - visibleItems + 1;
				carPosition = -adjPos;
				
				break;
			case "end":
				var cutOff = items - visibleItems;
				var clones = $(self.car).find("ul li:lt("+cutOff+")");
				$(clones).reverse().clone().insertAfter( $(self.car).find("ul li:last-child") );
				$(self.car).find("ul li:lt("+cutOff+")").remove();
				
				//Position adjustment
			
				$(self.car).find("ul").css({"left"	:	0});
				counter = 1;
				carPosition = 0;
				
				break;
			case "offset":
				var centerItem = Math.floor( visibleItems/2 );				
				var cutOff = items - (centerItem + 1);
				var clones = $(self.car).find("ul li:gt("+cutOff+")");
				$(clones).clone().insertBefore( $(self.car).find("ul li:first-child") );
				$(self.car).find("ul li:gt("+(cutOff + clones.length)+")").remove();
				
				//Position adjustment
				$(self.car).find("ul").css({"left"	:	0});
				counter = 1;
				carPosition = 0;
				
				break;
			default:
				return false;
		}
	};
	
	return this;

}

// Reverse jQuery Plugin

jQuery.fn.reverse = function()
{
	return this.pushStack(this.get().reverse(), arguments);
};

