/*
 * jQuery customSlide plugin
 * @author Jonas Weidler (jquery@jonas-weidler.de)
 * @version 0.3.1
 * @date April 10, 2010
 * @category jQuery plugin
 * @copyright (c) 2010 Jonas Weidler
 * @license CC Attribution-Share Alike 3.0 - http://creativecommons.org/licenses/by-sa/3.0/
 */
// compatible with jQuery 1.2.6 (not tested :-)
(function($){
	$.fn.extend({ 
		customSlide: function(options) {
			var defaults = 
			{
				// design issues
				orientation:	'horizontal', // vertical
				viewportSize:	960, // width or height of the wrapping carousel container
				itemsPerSlide:	3, // number of items to be displayed in the viewport
				// remoteControls: false,
				
				transitionType:	'slide',
					fadeType:	'crossfade',	// or 'fadeinfadeout'
				transitionSpeed:1000,
				
				// auto play
				autoPlay: 		false,
					displayTime: 5000,
					autoPlayDirection: 'next', // prev
					autoPlayBehaviour: 'step', // continuous
					autoPlaySpeed: 6,
				
				// behavior
				step:			'single',	// or 'full'
				// either:
				slideBackEnd:	true,
				slideBackStart:	true,
				// or:
				infinite:		false,
				// … or none of it, of course.
				
				//mouseOffset: 1,
				
				itemByItem:		false,
				inactiveOpacity:0.36,
				fadeSpeed: 		80,
					
				navigation:		false,
				
				onSlideDone: function() {
					//alert('done');
				},
				
				reinitiate: function() {
					//alert('reinitiate');
					// add your functions here
					//Cufon.replace('#carousel-3 h2');
					//return true;
				}
			};
			var options = $.extend(defaults, options);
			
			return this.each(function() {
								
				var opt = options;
				var obj = $(this);
				var items = $("div.item", obj);
				
				var currentData =
				{
					numItems: items.length,
					item: 1,
					itemOffset: 0,
					
					currentItemSize: 0,
					itemSize: function()
								{
									if (opt.orientation == 'horizontal') return items.outerWidth();
									if (opt.orientation == 'vertical') return items.outerHeight();
								},
					itemSize2D: function()
								{
									if (opt.orientation == 'horizontal') return items.outerHeight();
									if (opt.orientation == 'vertical') return items.outerWidth();
								},
					
					maxOffset: function()
								{
									if (opt.orientation == 'horizontal') return opt.viewportSize - (items.length * items.outerWidth());
									if (opt.orientation == 'vertical') return opt.viewportSize - (items.length * items.outerHeight());
								},
					
					slideBackTo: 0,
					offset: 0,
					
					running: false,
					
					infiniteCounterNext: 1,
					infiniteCounterPrev: items.length-1,
					
					counter: 0
				};
				var cD = currentData;
				
				if (opt.step == 'single') cD.infiniteCounterNext = 1;
				if (opt.step == 'full') cD.infiniteCounterNext = opt.itemsPerSlide;
				
				var controls = $(".controls", obj);
				
				// hide control buttons if there's only one slide
				if (cD.numItems <= opt.itemsPerSlide && !opt.infinite) controls.css('display', 'none');
				if (opt.navigation && !opt.infinite && !opt.itemByItem) {
					$(controls).append('<ul class="navigation" />');
					var navigation = $(".navigation", controls);
					for (var i = 1; i <= cD.numItems; i++) {
						navigation.append('<li><a rel="'+i+'" href="#">'+i+'</a></li>');
						$("li:last a", navigation).click(function(event){
							slideAnimation(contents, ($(this).attr('rel')-1)*cD.itemSize()*-1, true);
							event.preventDefault();
						});
					}
				}
				
				// navigation for fade slideshow
				if (opt.navigation && opt.transitionType == 'fade') {
					$(controls).append('<ul class="navigation" />');
					var navigation = $(".navigation", controls);
					for (var i = 1; i <= cD.numItems; i++) {
						navigation.append('<li><a rel="'+i+'" href="#">'+i+'</a></li>');
						$("li:last a", navigation).click(function(event){
							$(".active", navigation).removeClass('active');
							fadeAnimation('direct', ($(this).attr('rel')-1));
							$(this).parent().addClass('active');
							event.preventDefault();
						});
					}
					$("li:first", navigation).addClass('active');
				}
				
				// debugging
				//$(obj).append('<div id="output" />');
				//$(obj).css('position', 'relative');
				
				var contents = $(".contents", obj);
				contents.wrap('<div class="carousel-container" />');
				var container = $(".carousel-container", obj);
				container.css({
					//overflow: 'hidden',
					position: 'relative'
				});
				contents.css({position: 'absolute', top: '0px', left: '0px'});
				
				if (opt.orientation == 'horizontal') {
					container.css({width: opt.viewportSize, height: cD.itemSize2D()});
					contents.css('width', '99999px');
					items.css('float', 'left');
				}
				if (opt.orientation == 'vertical') {
					container.css({height: opt.viewportSize, width: cD.itemSize2D()});
					items.css('float', 'none');
				}
				
				if (opt.itemByItem) {
					$("div.item", obj).fadeTo(1, opt.inactiveOpacity);
					
					$(obj).append('<div class="back-shade" />');
					var backShade = $(".back-shade", obj);
					
					if (opt.orientation == 'horizontal') $(".back-shade", obj).css({width: cD.itemSize() + 'px', height: cD.itemSize2D() + 'px'});
					if (opt.orientation == 'vertical') $(".back-shade", obj).css({width: cD.itemSize2D() + 'px', height: cD.itemSize() + 'px'});
					$(".back-shade", obj).css({
						position: 'absolute',
						left: '0px',
						top: '0px'
					});
				}
				
				function cloning(direction) {
					if (opt.transitionType == 'fade') var clonesOpacity = 0;
					else if (opt.itemByItem) var clonesOpacity = opt.inactiveOpacity;
					else var clonesOpacity = 1;
					if (direction == 'init') cD.itemOffset = 1;
					else if (direction == 'next') cD.itemOffset = opt.itemsPerSlide;
					if (opt.step == 'single') var imax = 1;
					else var imax = opt.itemsPerSlide;
					for (var i = 0; i < imax; i++) {
						if (direction != 'next') {
							$("div.item:eq("+cD.infiniteCounterPrev+")", obj)
							.clone()
							.insertBefore($("div.item:first", obj))
							.addClass("cloned")
							.removeClass("active")
							.fadeTo(1, clonesOpacity);
						}
						else $("div.item:eq(0)", obj).remove();
						if (direction == 'next' && opt.step == 'full') {
							$("div.item:eq("+(opt.itemsPerSlide-1)+")", obj)
							.clone()
							.appendTo(contents);
						}
						else if (direction != 'prev') {
							$("div.item:eq("+(1-i)+")", obj)
							.clone()
							.appendTo(contents)
							.addClass("cloned")
							.removeClass("active")
							.fadeTo(1, clonesOpacity);
						}
						else $("div.item:last", obj).remove();
					}
					if (opt.step == 'full' && direction == 'init') $("div.item:eq("+(i-1)+")", obj).clone().appendTo(contents);
					if (direction != 'next') {
						if (opt.orientation == 'horizontal' && opt.step == 'single') contents.css('left', (cD.itemSize())*-1+'px');
						if (opt.orientation == 'vertical' && opt.step == 'single') contents.css('top', (cD.itemSize())*-1+'px');
						if (opt.orientation == 'horizontal' && opt.step == 'full') contents.css('left', (opt.viewportSize)*-1+'px');
						if (opt.orientation == 'vertical' && opt.step == 'full') contents.css('top', (opt.viewportSize)*-1+'px');
					}
					else {
						if (opt.orientation == 'horizontal' && opt.step == 'single') contents.css('left', (cD.currentItemSize)*-1+'px');
						if (opt.orientation == 'vertical' && opt.step == 'single') contents.css('top', (cD.currentItemSize)*-1+'px');
						if (opt.orientation == 'horizontal' && opt.step == 'full') contents.css('left', (opt.viewportSize)*-1+'px');
						if (opt.orientation == 'vertical' && opt.step == 'full') contents.css('top', (opt.viewportSize)*-1+'px');
					}
					$(obj).queue(function() {
						opt.reinitiate();
						$(this).dequeue();
					});
				}
				if (opt.infinite && opt.transitionType == 'slide') cloning('init');
				
				if (opt.transitionType == 'fade') {
					obj.addClass("fade");
					items = $("div.item", obj);
					items.css('position', 'absolute');
					//items.css('zIndex', '0');
					items.fadeTo(1, 0);
					contents.css('left', '0px');
					for (var i = 1; i <= cD.numItems; i++) {
						items.eq(i-1).attr('rel', i);
					}
				}
				
				if (opt.infinite && opt.transitionType == 'slide') $("div.item:eq(1)", obj).fadeTo(1, 1).addClass('active').fadeIn(1);
				else $("div.item:eq(0)", obj).fadeTo(1, 1).addClass('active');
								
				function debug(text) {
					$("#output").html('Running: '+cD.running+'<br />'+text);
				}
				
				function slideAnimation(element, amount, absolute) {
					if (!absolute) amount = '+=' + amount;
					if (opt.orientation == 'horizontal') element.animate({left: amount + 'px'}, opt.transitionSpeed);
					if (opt.orientation == 'vertical') element.animate({top: amount + 'px'}, opt.transitionSpeed);
				}
				
				function fadeAnimation(direction, pos) {
					activeItem = $(".item.active", obj);
					if (direction == 'next') {
						activeItem.fadeTo(opt.transitionSpeed, 0).removeClass("active");
						if (activeItem.attr("rel") == cD.numItems) {
							items.eq(0).fadeTo(opt.transitionSpeed, 1, function(){
								opt.onSlideDone();
								cD.running = false;
							}).addClass("active");
						}
						else {
							activeItem.next().fadeTo(opt.transitionSpeed, 1, function(){
								opt.onSlideDone();
								cD.running = false;
							}).addClass("active");
						}
					}
					else if (direction == 'prev') {
						activeItem.fadeTo(opt.transitionSpeed, 0).removeClass("active");
						if (activeItem.attr("rel") == 1) {
							items.eq(cD.numItems-1).fadeTo(opt.transitionSpeed, 1, function(){
								opt.onSlideDone();
								cD.running = false;
							}).addClass("active");
						}
						else {
							activeItem.prev().fadeTo(opt.transitionSpeed, 1, function(){
								opt.onSlideDone();
								cD.running = false;
							}).addClass("active");
						}
					}
					else if (direction == 'direct') {
						activeItem.fadeTo(opt.transitionSpeed, 0).removeClass("active");
						items.eq(pos).fadeTo(opt.transitionSpeed, 1, function(){
							opt.onSlideDone();
							cD.running = false;
						}).addClass("active");
					}
				}
				
				function fadeItem() {
					items.eq(cD.itemOffset).animate({opacity: opt.inactiveOpacity}, opt.fadeSpeed).removeClass('active');
					items.eq(cD.itemOffset).queue(function() {
						slideAnimation(backShade, cD.currentItemSize);
						backShade.queue(function() {
							cD.item = cD.item + cD.counter;
							cD.itemOffset = cD.itemOffset + cD.counter;
							items.eq(cD.itemOffset).animate({opacity: 1}, opt.fadeSpeed, function(){opt.onSlideDone();}).addClass('active');
							cD.running = false;
							$(this).dequeue();
						});
						$(this).dequeue();
					});
				}
				
				function singleSlide() {
					if (opt.itemByItem) items.eq(cD.itemOffset).animate({opacity: opt.inactiveOpacity}, opt.fadeSpeed).removeClass('active');
					items.eq(cD.itemOffset).queue(function() {
						slideAnimation(contents, -cD.currentItemSize);
						contents.queue(function() {
							cD.itemOffset = cD.itemOffset + cD.counter;
							if (opt.itemByItem) $("div.item:eq("+cD.itemOffset+")", obj).animate({opacity: 1}, opt.fadeSpeed, function(){opt.onSlideDone();}).addClass('active');
							if (opt.infinite) {
								cloning('next');
								opt.onSlideDone();
							}
							else opt.onSlideDone();
							cD.running = false;
							$(this).dequeue();
						});
						$(this).dequeue();
					});
				}
				
				function fullSlide(viewportSize) {
					slideAnimation(contents, -viewportSize);
					contents.queue(function() {
						if (opt.infinite) {
							cloning('next');
						}
						opt.onSlideDone();
						cD.running = false;
						$(this).dequeue();
					});
				}
				
				function backSlide(currentItem, itemOffset, moveBackShadeTo) {
					if (opt.itemByItem) {
						$("div.item:eq("+cD.itemOffset+")", obj).animate({opacity: opt.inactiveOpacity}, opt.fadeSpeed).removeClass('active');
						$("div.item:eq("+cD.itemOffset+")", obj).queue(function() {
							slideAnimation(backShade, moveBackShadeTo, true);
							backShade.queue(function() {
								$("div.item:eq("+itemOffset+")", obj).animate({opacity: 1}, opt.fadeSpeed, function(){
									opt.onSlideDone();
									// works for iBi, inf
									cD.running = false;
								}).addClass('active');
								$(this).dequeue();
							});
							$(this).dequeue();
						});
					}
					slideAnimation(contents, cD.slideBackTo, true);
					contents.queue(function() {
						if (!opt.itemByItem) opt.onSlideDone();
						
						cD.itemOffset = itemOffset;
						cD.item = currentItem;
						
						if (opt.infinite) {
							cloning('prev');
							opt.onSlideDone();
						}
						
						// previous item, inf
						if (itemOffset == 1 && !opt.itemByItem) {
							cD.running = false;
						}
						else if (!opt.infinite && !opt.itemByItem) {
							cD.running = false;
						}
						// works for inf, fullSlide
						else if (opt.infinite && !opt.itemByItem && opt.step == 'full') cD.running = false;
						$(this).dequeue();
					});
				}
				
				function slideInit(direction)
				{
					items = $("div.item", obj);
					if (opt.orientation == 'horizontal') cD.offset = parseInt(contents.css('left'));
					if (opt.orientation == 'vertical') cD.offset = parseInt(contents.css('top'));
					
					if (direction == 'next' && !cD.running) 
					{
						cD.running = true;
						if (opt.transitionType == 'slide') {
							cD.currentItemSize = cD.itemSize();
							cD.counter = 1;
								
							if (opt.itemByItem && opt.step == 'single' && cD.item != opt.itemsPerSlide)
							{
								fadeItem();
							}
							else if (cD.offset > cD.maxOffset())
							{
								if (opt.step == 'single') singleSlide();
								if (opt.step == 'full') fullSlide(opt.viewportSize);
							}
							else if (opt.slideBackEnd && !opt.infinite)
							{
								cD.slideBackTo = 0;
								cD.item = 1;
								backSlide(1, 0, 0);
							}
							else cD.running = false;
						}
						else if (opt.transitionType == 'fade') {
							fadeAnimation('next');
						}
					}
					
					if (direction == 'prev' && !cD.running) 
					{
						cD.running = true;
						if (opt.transitionType == 'slide') {
							cD.currentItemSize = (cD.itemSize())*-1;
							cD.counter = -1;
								
							if (opt.itemByItem && opt.step == 'single' && cD.item != 1)
							{
								fadeItem();
							}
							else if (cD.offset < 0 && !opt.infinite)
							{
								if (opt.step == 'single') singleSlide();
								if (opt.step == 'full') fullSlide((opt.viewportSize)*-1);
							}
							else if (opt.slideBackStart && !opt.infinite)
							{
								cD.slideBackTo = '-' + cD.itemSize() * (cD.numItems - opt.itemsPerSlide);
								cD.item = opt.itemsPerSlide;
								backSlide(opt.itemsPerSlide, cD.numItems-1, cD.itemSize() * (opt.itemsPerSlide-1));							
							}
							else if (opt.infinite)
							{
								if (opt.step == 'single' && cD.offset == (cD.itemSize())*-1) {
									cD.slideBackTo = 0;
									cD.item = 2;
									backSlide(1, 1, 0);
								}
								else if (opt.step == 'full' && cD.offset == opt.viewportSize*-1) {
									cD.slideBackTo = 0;
									cD.item = 4;
									backSlide(1, 3, 0);
								}
								else {
									if (opt.step == 'single') singleSlide();
									if (opt.step == 'full') fullSlide((opt.viewportSize)*-1);
								}
							}
							else cD.running = false;
						}
						else if (opt.transitionType == 'fade') {
							fadeAnimation('prev');
						}
					}
					
				}
				
				//$(obj).append('<div id="output" />');
				
				function mouseScroll() {
					$(obj).mouseenter(function(e){
						contents.stop();
					}).mouseleave(function(e){
						autoplay();
					});
				}
				
				function autoplay()
				{
					if (opt.autoPlayBehaviour == 'step') {
						setTimeout(function(){
							if (opt.autoPlayDirection == 'next') $(".controls .next", obj).click();
							if (opt.autoPlayDirection == 'prev') $(".controls .prev", obj).click();
							autoplay();
							cD.running = true;
						}, opt.displayTime);
					}
					else if (opt.autoPlayBehaviour == 'continuous') {
						if (opt.autoPlayDirection == 'next') {
							contents.animate({left: opt.viewportSize-cD.itemSize()*cD.numItems+'px'}, {duration: (1/opt.autoPlaySpeed)*cD.numItems*2000, specialEasing: {left: 'linear'}, complete: function() {
								$(this).animate({left: '0px'}, {duration: (1/opt.autoPlaySpeed)*cD.numItems*2000, specialEasing: {left: 'linear'}, complete: function() {autoplay();}});
							}});
						}
					}
				}
				
				$(".controls .next", obj).click(function(event){
					slideInit('next');
					event.preventDefault();
				});
				
				$(".controls .prev", obj).click(function(event){
					slideInit('prev');
					event.preventDefault();
				});
				
				if (opt.autoPlay == true) autoplay();
				
				//mouseScroll();
				
			});
		}
	});
})(jQuery);
