/**
 * Infinite Carousel jQuery Plugin
 */
(function( $ ){

$.fn.infiniteCarousel = function(options) {
	
	// Extend our default options with those provided.
	var opts = $.extend({}, $.fn.infiniteCarousel.defaults, options);
	
	// Repeat Function
	function repeat(str, num) {
		return new Array( num + 1 ).join( str );
	}
  
  return this.each(function () {
  	
  	// Save our object
  	var $this = $(this);
  	
  	// Build element specific options
  	// This lets me access options with this syntax: o.optionName
  	var o = $.meta ? $.extend({}, opts, $this.data()) : opts;
		
  	// Initialize Element Specific Variables
    var $wrapper = $this.find('.wrapper'),
    		$slider = $wrapper.find('> ul').addClass('slider'),
    		$items = $slider.find('> li').addClass('item'),
    		$single = $items.filter(':first'),
        
    		$singleWidth = $single.outerWidth(),
    		$visibleWidth = Math.ceil($wrapper.width() / $singleWidth),
    		$visible = Math.ceil($wrapper.width() / $singleWidth),
        
    		$currentPage = 1,
    		$pages = Math.ceil($items.length / $visible),
        
				$sliderWidth = ($wrapper.innerWidth() * 2) + ($wrapper.innerWidth() * $pages);
		
		$wrapper.css('overflow', 'hidden');
		$slider.css('width', $sliderWidth).attr('id', 'page-' + $currentPage);
		
    // 1. Pad so that 'visible' number will always be seen, otherwise create empty items
    if (($items.length % $visible) != 0) {
			$slider.append(repeat('<li class="empty item" />', $visible - ($items.length % $visible)));
			$items = $slider.find('> li');
    }

    // 2. Top and tail the list with 'visible' number of items, top has the last section, and tail has the first
    $items.filter(':first').before($items.slice(- $visible).clone().addClass('cloned item'));
    $items.filter(':last').after($items.slice(0, $visible).clone().addClass('cloned item'));
    $items = $slider.find('> li'); // reselect
    
    // 3. Set the left position to the first 'real' item
    $wrapper.scrollLeft($singleWidth * $visibleWidth);
        
		// 4. paging function
		function gotoPage(page) {
			
			var dir = page < $currentPage ? -1 : 1,
					n = Math.abs($currentPage - page),
					left = $singleWidth * dir * $visibleWidth * n;
			
			if (o.effect === 'fade') {
				
				// Animate the image transition
				
				$wrapper.filter(':not(:animated)').animate({
			    opacity : 0
			  }, {
			    duration: 500,  
			    complete: function() {
			    	
						$wrapper.animate({
							scrollLeft : '+=' + left
						}, 1, function () {
							if (page == 0) {
								$wrapper.scrollLeft($singleWidth * $visibleWidth * $pages);
								page = $pages;
							} else if (page > $pages) {
								$wrapper.scrollLeft($singleWidth * $visibleWidth);
								// reset back to start position
								page = 1;
							} 

						});
			
						$wrapper.animate({
					    opacity : 1
					  }, {
					    duration: 500,  
					    complete: function() {

								$currentPage = page;

								$slider.attr('id', 'page-' + $currentPage);
								$this
									.find('.' + o.dotNavClass + ' a')
									.removeClass('active')
								$this
									.find('.' + o.dotNavClass + ' a[href="#page-'+ $currentPage +'"]')
									.addClass('active');

							}
					  });
						
					}
			  });
				
			} else {
			
				$wrapper.filter(':not(:animated)').animate({
					scrollLeft : '+=' + left
				}, 500, function () {
					if (page == 0) {
						$wrapper.scrollLeft($singleWidth * $visibleWidth * $pages);
						page = $pages;
					} else if (page > $pages) {
						$wrapper.scrollLeft($singleWidth * $visibleWidth);
						// reset back to start position
						page = 1;
					} 
				
				$currentPage = page;
						
				$slider.attr('id', 'page-' + $currentPage);
				$this
					.find('.' + o.dotNavClass + ' a')
					.removeClass('active')
				$this
					.find('.' + o.dotNavClass + ' a[href="#page-'+ $currentPage +'"]')
					.addClass('active');
	
				});
			
			}
			
			return false;
		}
    
    // Switch every couple seconds
		function autoScroll() {
	    intervalID = setInterval(function() {
	      gotoPage($currentPage + 1);
			}, o.autoRotateSpeed);
			return intervalID;
		}
		
		if (o.autoRotate) {
		
			var intervalID = autoScroll();
			
			$this.hover(function() {
				clearInterval(intervalID);
			}, function() {
				clearInterval(intervalID);
				intervalID = autoScroll();
			});
		
		}
        
    // Add Navigation
    if (o.leftRightNav) {
			if (o.navContainer) {
				if (o.leftNav) $this.find('.' + o.navContainer).append('<span class="' + o.leftRightNavClass + ' ' + o.leftNavClass + '"></span>');
	    	if (o.rightNav) $this.find('.' + o.navContainer).append('<span class="' + o.leftRightNavClass + ' ' + o.rightNavClass + '"></span>');
			} else {
	    	if (o.leftNav) $wrapper.after('<span class="' + o.leftRightNavClass + ' ' + o.leftNavClass + '"></span>');
	    	if (o.rightNav) $wrapper.after('<span class="' + o.leftRightNavClass + ' ' + o.rightNavClass + '"></span>');
    	}
		}
    if (o.navContainer) {
			if (o.dotNav) $this.find('.' + o.navContainer).append('<div class="' + o.dotNavClass + '"></div>');
    } else {
			if (o.dotNav) $wrapper.after('<div class="' + o.dotNavClass + '"></div>');
		}

    for (var i = 1; i < ($pages + 1); i++ ) {
			$(this)
				.find('.' + o.dotNavClass)
				.append('<a href="#page-' + i + '">' + i + '</a>');
		}
		$(this)
			.find('.' + o.dotNavClass + ' a[href="#page-' + $currentPage + '"]')
			.addClass('active');
        
    // Bind to the forward and back buttons
    $('.' + o.leftNavClass, this).click(function () {
			return gotoPage($currentPage - 1);                
    });
    
    $('.' + o.rightNavClass , this).click(function () {
			return gotoPage($currentPage + 1);
    });
    
    // Bind to the Dot Navigation
    $('.' + o.dotNavClass + ' a', this).click(function() {
			return gotoPage( $(this).text() );
		});
    
    // create a public interface to move to a specific page
    $(this).bind('infiniteCarousel.goto', function (event, page) {
        gotoPage(page);
    });
    
  });
  
};

/**
 * Plugin Defaults
 */
$.fn.infiniteCarousel.defaults = {

	effect : 'scroll',

	autoRotate : true,
	autoRotateSpeed : 5000,
	
	navContainer: false,
	
	leftRightNav : true,
	leftNav		: true,
	rightNav	: true,
	
	leftRightNavClass : 'nav-item',
	leftNavClass : 'nav-left',
	rightNavClass : 'nav-right',
	
	dotNav 		: true,
	dotNavClass : 'nav-dot'
	
};

})( jQuery );
