/**
 * xCarousel jQuery carousel plugin made by Alex Shustov
 * The progenitor of this plugin was bxSlider plugin made by Steven Wanderski (http://bxslider.com)
 *
 * Released under the GPL license: http://www.gnu.org/licenses/gpl.html
 * Features:
 * - numeric or graphic pager
 * - prev/next buttons
 * - ability to show and scroll any amount of frames at a time
 * - any direction sliding animation
 * - auto scrolling
 *
 * v 1.1
 */
(function($){
	$.fn.xCarousel=function(options) {
		var defaults={
			speed:500,			// animation speed
			start:0,			// initially selected frame
			interval:2000,		// interval between animations
			direction:'left',	// left, right, top, bottom
			scroll:1,			// number of frames to scroll at a time
			auto:false,			// auto scroll
			pagerSel:false,			// pager selector
			pageActiveCls:'active',	// active page class
			nextLinkSel:'.next',	// next link selector
			prevLinkSel:'.prev'		// prev link selector
		};

		var o = $.extend(defaults, options);
		return this.each(function() {
			var $this = $(this).wrapInner('<div/>');
			var $clip = $this.children().eq(0).css({'overflow':'hidden', 'position':'relative', 'width':$this.width(), 'height':$this.height()});
			var $list = $clip.children().eq(0); // ul | ol
			var $frames = $list.children(); // li
			var length = $frames.length; // total number of frames
			var currentIndex = o.start;
			var winSize, width, height, timer;
			var upright = o.direction=='top' || o.direction=='bottom'; // vertical or horizontal orientation
			var preorder = o.direction=='left' || o.direction=='top'; // straight or reverse order

			if(upright) {
				height = $frames.eq(currentIndex).outerHeight(true);
				winSize = Math.ceil($clip.height() / height);
				rewindIndex(currentIndex); // rewinds index if there is no place for the next iteration
				$list.css({'position':'relative', 'top':-(currentIndex+winSize) * height, 'height':height * (length + 2 * winSize)});
			} else {
				width = $frames.eq(currentIndex).outerWidth(true);
				winSize = Math.ceil($clip.width() / width);
				rewindIndex(currentIndex); // rewinds index if there is no place for the next iteration
				$frames.css({'float':'left'});
				$list.css({'position':'relative', 'left':-(currentIndex+winSize) * width, 'width':width * (length + 2 * winSize)});
			}

			// appending/prepending winSize cloned frames
			$list.append($frames.slice(0, winSize).clone()).prepend($frames.slice(-winSize).clone());

			// pager controll (dots)
			var $pager = $(o.pagerSel);
			$pager.click(function(e) {
				var $a = $(e.target);
				if($a.is('a')) {
					showFrame(parseInt($a.attr('rel')));
					e.preventDefault();
				}
			});
			updatePager();

			// arrows controll
			$(o.nextLinkSel).click(function(e) {
				if(!$list.is(':animated'))
					showFrame(currentIndex-o.scroll);
				e.preventDefault();
			});
			$(o.prevLinkSel).click(function(e) {
				if(!$list.is(':animated'))
					showFrame(currentIndex+o.scroll);
				e.preventDefault();
			});

			// auto rotation
			if(o.auto) {
				timer = initTimer();
				// stops timer while hover
				$this.hover(function() {
					clearInterval(timer);
					timer = undefined;
				}, function() {
					if(timer == undefined)
						timer = initTimer();
				});
			}

			function updatePager() {
				var $links = $pager.children();
				$links.removeClass(o.pageActiveCls).eq(currentIndex).addClass(o.pageActiveCls);
			}

			function initTimer() {
				return setInterval(function() {
					showFrame();
				}, o.interval);
			}

			function showFrame(index) {
				var params = {};
				if(index != undefined)
					currentIndex = index;
				else
					currentIndex = preorder ? currentIndex + o.scroll : currentIndex - o.scroll;
				$list.stop(); // stop current animation
				params[upright ? 'top' : 'left'] = -(upright ? height : width) * (currentIndex + winSize);
				$list.animate(params, o.speed, 'linear', function() {
					if(rewindIndex())
						$list.css(upright ? 'top' : 'left', -(upright ? height : width) * (currentIndex + winSize));
					updatePager();
				});
			}

			// rewinds index if there is no place for next iteration
			function rewindIndex() {
				if(length-currentIndex < winSize) {
					currentIndex -= length;
					return true;
				} else if(currentIndex < 0) {
					currentIndex += length;
					return true;
				}
				return false;
			}
		});
	};
})(jQuery)
