/* requires scrollTo and serialScroll */
(function($) {
$.fn.hoverClass = function(c) {
	return $(this).hover(
		function() { $(this).addClass(c); },
		function() { $(this).removeClass(c); }
	);
}

var carouselCount = 1;

$.fn.dsCarousel = function(options) {

	return $(this).each(function() {
		var defaults = {
			contentDestination: '#carousel_content',
			contentSourceSelector: 'div.content',
			listContainer: $(this),
			hoverClassName: 'hover',
			currentClassName: 'current',
			clickableClassName: 'js-clickable',
			dataSource: null, // if this is set, make sure dataSourceArgs and jsonProcessor are set too
			dataSourceArgs: {},
			jsonProcessor: function(v) { return v; },
			initialFetches: 0,
			axis: 'y', // haven't tested this, use caution if you override it
			step: 1,
			easing: '',
			exclude: 0,
			duration: 500,
			constant: true
		};

		var settings = $.extend(defaults,options);

		var $listContainer = settings.listContainer;
		if (settings.ulSelector) {
			var $ul = $listContainer.find(settings.ulSelector);
		} else {
			var $ul = $listContainer.find('ul:first');
		}
		
		if (settings.axis == 'x') {
			$listContainer.wrap('<div id="js-carouselListContainer-'+carouselCount+'" class="slider"></div>');
		} else {
			$listContainer.wrap('<div id="js-carouselListContainer-'+carouselCount+'"></div>');
		}
		var showContent = function(e) {
			e.preventDefault();
			var $this = $(this);
			$this.addClass(settings.currentClassName).siblings().removeClass(settings.currentClassName);
			$(settings.contentDestination).html( $this.find(settings.contentSourceSelector).html() );
		};

		$ul.scrollTo({top:0,left:0}).find('li:first').addClass(settings.currentClassName);
		$(settings.contentDestination).html( $ul.find('li:first ' + settings.contentSourceSelector).html() );

		$ul.find('li').
			hoverClass(settings.hoverClassName).
			addClass(settings.clickableClassName).
			click(showContent).
			find(settings.contentSourceSelector).
				hide();

		// only build the carousel if there are enough items to justify it
		if ($ul.find('li').size() > settings.step) {
			  $ul.
			  			 	before('<div class="prev nav inactive"><div></div></div>').
			  			 	after('<div class="next nav"><div></div></div>');
			
			$listContainer.find('div.nav').hoverClass(settings.hoverClassName);

			var fetches = settings.initialFetches;

			var nextNav = '#js-carouselListContainer-'+carouselCount+' div.next';
			var prevNav = '#js-carouselListContainer-'+carouselCount+' div.prev';

			$ul.serialScroll({
				items: 'li',
				axis: settings.axis,
				jump: false,
				next: nextNav,
				prev: prevNav,
				start: 0,
				lazy: true,
				duration: settings.duration,
				cycle: false,
				step: settings.step,
				exclude: settings.exclude,
				easing: settings.easing,
				constant: settings.constant,
				onBefore: function(e,elem,$pane,$items,pos) {
					// enable/disable prev nav
					if (pos > 0) { $listContainer.find('div.prev').removeClass('inactive'); } 
					else { $listContainer.find('div.prev').addClass('inactive'); }
						
					if ($(this).hasClass('next') && ($items.size() < (pos+(settings.step*2))) && settings.dataSource) {
						var dataSourceArgs = { 
							itemsLoaded: $items.size(), 
							itemsToRetrieve: settings.step,
							fetches: fetches
						};
						dataSourceArgs = $.extend(dataSourceArgs,settings.dataSourceArgs);
						$.getJSON(
							settings.dataSource,
							dataSourceArgs,
							function(json) {
								fetches++;

								$.each(json,function(i,v) {
									var html = settings.jsonProcessor(v);
									$listContainer.find('ul:first').append('<li>' + html + '</li>'); // make sure the items are added inside the ul
								});

								$ul.find('li').not('.'+settings.clickableClassName).
									hoverClass(settings.hoverClassName).
									addClass(settings.clickableClassName).
									click(showContent).
									find(settings.contentSourceSelector).
										hide();
							}
						);
					}
					
					// enable/disable next nav
					if ((pos + (settings.step)) >= $ul.find('li').size()) {
						$listContainer.find('div.next').addClass('inactive');
					} else {
						$listContainer.find('div.next').removeClass('inactive');
					}
					
					return true;
				},
				onAfter: function(elem) { /* $(elem).trigger('click'); */ }

			});
		}
		carouselCount++; //increment the counter regardless if a carousel was made
	});
};
})(jQuery);
