/**
 * @author John Noel <john.noel@rckt.co.uk>
 * @copyright rckt 2011 <http://www.rckt.co.uk>
 * @package MuseumsSheffield
 */

/**
 * Scroller plugin
 * Turns a list into a scroller / carousel / slider / whatever
 *
 * @author John Noel <john.noel@rckt.co.uk>
 * @copyright rckt http://www.rckt.co.uk/
 * @version 1.2
 * @package MuseumsSheffield
 * @todo Allow choosing of pagination CSS classes
 * @todo Allow external calling of advance / retreat
 */
(function($) {
	$.fn.scroller = function(option) { 
		option = $.extend({}, $.fn.scroller.option, option);
		
		return this.each(function() {
			var $this = $(this),
				transitioning = false,
				slideCount = $(option.slidesSelector, $this).length;
			
			option.paginationBuild &= (slideCount > option.slidesPerScroll);
			
			// add pagination
			if(option.paginationBuild)
			{
				var pageCount = Math.ceil(slideCount / option.slidesPerScroll);
				var pages = '';
				for(var i = 1; i <= pageCount; i++)
				{
					pages += '<li>'+i+'</li>';
				}
				
				$('<div class="pagination" />')
					.append('<span class="previous">Previous</span>')
					.append('<span class="next">Next</span>')
					.append('<ul>'+pages+'</ul>')
					.appendTo($this);
			}
			
			if(option.pagination)
			{
				$('.pagination li', $this).first().addClass('on');
			}
			
			// "square off" scroller
			if((slideCount % option.slidesPerScroll) != 0)
			{
				var p = $(option.slidesSelector, $this).first().parent();
				var toInsert = $(option.slidesSelector, $this)
					.slice(0 - (slideCount % option.slidesPerScroll))
					.each(function() {
						p.append(this.cloneNode(false)); // not a deep copy
					});
			}
			
			// advance
			var advance = function(count) {
				if(!transitioning)
				{
					transitioning = true;
				
					// pagination
					if(option.pagination)
					{
						var next = $('.pagination li.on', $this).nextAll();
						var n = (next.length < count) ?
							$('.pagination li', $this).eq(1 - Math.abs(next.length - count)) :
							next.eq(count - 1); // 0 indexed
						
						n.addClass('on').siblings().removeClass('on');
					}
					
					var slides = $($(option.slidesSelector, $this).slice(0, option.slidesPerScroll * count));
					var width = 0;
					slides.each(function() {
						width += $(this).outerWidth(true);
						$(this).parent().append(this.cloneNode(true));
					});
					
					slides.first().animate({ marginLeft: 0 - width }, 700, function() {
						transitioning = false;
						slides.remove();
					});
				} // !transitioning
			}; // advance()
			
			// retreat
			var retreat = function(count) {
				if(!transitioning)
				{
					transitioning = option.slidesPerScroll;
					
					if(option.pagination)
					{
						// pagination
						var prev = $('.pagination li.on', $this).prevAll();
						var p = (prev.length < count) ?
							$('.pagination li', $this).eq(prev.length - count) :
							prev.eq(count - 1);
						p.addClass('on').siblings().removeClass('on');
					}
					
					// select slides > slice > turn into JS array > reverse > turn back into JQuery obj
					var slides = $($.makeArray($(option.slidesSelector, $this).slice(0 - (option.slidesPerScroll * count))).reverse());
					var width = 0;
					slides.each(function() {
						width += $(this).outerWidth(true);
						$(this).parent().prepend(this.cloneNode(true));
					});
					
					$(option.slidesSelector, $this).first()
						.css({ marginLeft: 0 - width+'px' })
						.animate({ marginLeft: 0 }, 700, function() {
							transitioning = false;
							slides.remove();
						});
				} // !transitioning
			}; // retreat()
			
			if(option.pagination)
			{
				$('.pagination .next', $this).click(function(evt) { evt.stopPropagation(); advance(1); });
				$('.pagination .previous', $this).click(function(evt) { evt.stopPropagation(); retreat(1); });
				$('.pagination li', $this).click(function(evt) {
					evt.stopPropagation();
					var $elem = $(evt.currentTarget);
					
					var target = $elem.prevAll().length;
					var current = $elem.siblings('.on').prevAll().length;
					
					// check to make sure not navigating to same element
					if(!$elem.hasClass('on'))
					{
						// by default advance
						var diff = target - current;
						var nDiff = diff;
						
						// but if moving over half of the items, retreat instead
						if(Math.abs(diff) > Math.floor($elem.siblings().andSelf().length / 2))
						{
							nDiff = Math.abs(nDiff) - $elem.siblings().andSelf().length;
							nDiff *= (diff < 0) ? -1 : 1;
						}
						
						if(nDiff > 0)
						{
							advance(nDiff);
						}
						else
						{
							retreat(Math.abs(nDiff));
						}
					}
				});
			} // option.pagination
		});
	};
	
	$.fn.scroller.option = {
		slidesPerScroll: 1, // how many slides per click
		slidesSelector: 'ul.slides li', // how to select the slides (scoped to the element)
		paginationBuild: true, // whether to build the pagination or not
		pagination: true // whether to operate pagination at all
	};
})(jQuery);

$('#homepage article .slideshow').scroller();
