/**
 * @projectDescription: jQuery plugin for creating a revolving series of content slides
 */

(function($){
	
	$.fn.revolver = function(opts) {
		
		opts = $.extend({
			duration: 1000,
			interval: 8000,
			prev: null,
			next: null,
			slideSelector: null,
			pager: null,
			transition: 'slideLeft'
		}, opts);
		
		var $obj = this;
		
		$obj.currentPos = 0;
		$obj.totalSlides = $obj.find(opts.slideSelector).length;
		$obj.busy = false;
			
		if($obj.totalSlides < 2) return;
			
		return this.each(function() {
			var maxHeight = 0;
			var startPos = 0;

			if(opts.pager) $(opts.pager).empty();
			
			$obj.find(opts.slideSelector).each(function(i) {
				maxHeight = Math.max(maxHeight, $(this).outerHeight(true));
				
				i === 0 ? startPos = 0 : startPos = $obj.width();

				$(this).attr('aria-hidden', true).css({
					'width': $(this).innerWidth(),
					'position': 'absolute',
					'top': 0,
					'left': startPos,
					'display': 'none'
				});
				
				$('#smallCarousel').attr('aria-live','polite').attr('aria-relevant', 'all');
				
				$(".gallery a:eq(0)").addClass('current').attr('aria-hidden', false).css({
						'display': 'block'
					});
													
				if(opts.pager) {
					$(opts.pager).append('<li><a href="#">Carousel item '+(i+1)+'</a></li>');
					$(opts.pager).parents('.galleryControls').css({
						'display': 'block'
					});
				}
			});
		
			$obj.css({
				'height': maxHeight,
				'overflow': 'hidden',
				'position': 'relative'
			});
			
			if(opts.prev) {
				$(opts.prev).show().bind('click', function(e) {
					moveTo($obj.currentPos === 0 ? $obj.totalSlides-1 : $obj.currentPos-1, e);
					return false;
				});					
			}				
			
			if(opts.next) {
				$(opts.next).show().bind('click', function(e) {
					moveTo($obj.currentPos === $obj.totalSlides-1 ? 0 : $obj.currentPos+1, e);
					return false;
				});
			}
			
			if(opts.pager) {
				$(opts.pager).show().find('a').bind('click', function(e) {
					moveTo($(opts.pager).find('a').index(e.target), e);
					return false;
				});
				$(opts.pager).find('a').eq(0).addClass('selected').attr('title', 'Current carousel item');
			}
			
			if(opts.interval > 0) {
				resume();
				
				$(opts.pager+', '+opts.prev+', '+opts.next).hover(function() {
					clearInterval($obj.autoplay);
				}, function() {
					resume();
				});					
				
			}
			
			
		});
		
		/**
		 * Animates the current slide out and the next slide in
		 * 
		 * @param {integer} nextSlide -  index of the next slide to be animated in
		 */
		function moveTo(nextSlide, e) {
			getAnimationProperties(opts.transition, nextSlide, e);
			
			if(!$obj.busy && $obj.currentPos != nextSlide) {
				$obj.busy = true;
				
				if(opts.cssBefore) $obj.children().eq(nextSlide).css(opts.cssBefore);
				
				$obj.children().eq($obj.currentPos).animate(opts.animOut, {
					duration: opts.duration,
					step: function(now) {
						getAnimationProperties(opts.transition, nextSlide, e, now);
						$obj.children().css('display', 'none').removeClass('current').attr('aria-hidden', true);
						$obj.children().eq(nextSlide).css(opts.cssStep);
						$obj.children().eq(nextSlide).css('display', 'block').addClass('current').attr('aria-hidden', false);
					},
					complete: function() {
						$obj.children('a[class="current"]').focus();
						$obj.currentPos = nextSlide;
						$obj.busy = false;
					}
				});
				
				if(opts.pager) {
					$(opts.pager).find('a').removeClass('selected').attr('title', null);
					$(opts.pager).find('a').eq(nextSlide).addClass('selected').attr('title', 'Current carousel item');	
				}
			}
		}
		
		/**
		 * Sets the interval for autoplay
		 */
		function resume() {
			$obj.autoplay = setInterval(function() {
				moveTo($obj.currentPos === $obj.totalSlides-1 ? 0 : $obj.currentPos+1, null);
			}, opts.interval);
		}
		
		/**
		 * Defines maps of CSS properties used by the jQuery animate method in the moveTo function
		 * 
		 * @param {string} transition - name of the transition defined in the options
		 * @param {integer} stepVal - the numeric value of the property being animated at each step  
		 */
		function getAnimationProperties(transition, nextSlide, e, stepVal) {
			switch(transition) {
				case 'slideLeft':
					opts.animOut = { left: -$obj.width() }
					opts.cssStep = { left: stepVal+$obj.width() }
					break;
				case 'slideRight':
					opts.animOut = { left: $obj.width() }
					opts.cssBefore = { left: -$obj.width() }
					opts.cssStep = { left: stepVal-$obj.width() }
					break;
				case 'slideX':
					if(nextSlide < $obj.currentPos && (e && e.target.id != opts.next.slice(1)) || (e && e.target.id === opts.prev.slice(1))) {
						opts.animOut = { left: $obj.width() }
						opts.cssBefore = { left: -$obj.width() }
						opts.cssStep = { left: stepVal-$obj.width() }
					}
					else {
						opts.animOut = { left: -$obj.width() }
						opts.cssBefore = { left: $obj.width() }
						opts.cssStep = { left: stepVal+$obj.width() }					
					}
					break;
				case 'slideUp':
					opts.animOut = { top: -$obj.height() }
					opts.cssBefore = { left: 0 }
					opts.cssStep = { top: stepVal+$obj.height() }
					break;
				case 'fade':
					opts.animOut = { opacity: 0 }
					opts.cssBefore = { left: 0 }
					opts.cssStep = { opacity: 1-stepVal }
					break;
			}
		}
		
	}
	
})(jQuery);

(function($){

	$(function () {
		$('#smallCarousel .gallery').revolver({
			prev: '#galleryPrev',
			next: '#galleryNext',
			pager: '#galleryPager',
			slideSelector: 'a',
			interval: 0,
			duration: 700,
			transition: 'slideX'
		});
	});
	
})(jQuery);

