/*
* @plugin: recycle build 1.0alpha
* @author: Jonathan Lau
* www.jonathanlau.co.uk
*/

;(function($){
	
	$.fn.recycle = function(opts){
		
		var defaults = {
			visible: 1,
			shift: 1,
			direction: null,
			cyclic: false,
			fade: false,
			btnPrev: null,
			btnNext: null,
			btnGo: null,
			pager: null,
			auto: false,
			start: 0,
			delay: 5000,
			speed: 600,
			easing: null,
			loaderClass: "loader",
			activeClass: "active",
			lastClass: "last",
			onInit: null,
			onInitComplete: null,
			onBeforeTransition: null,
			onAfterTransition: null,
			cleartype: !$.support.opacity,
			mousewheel: false
		};
		var opts = $.extend(defaults, opts);
		
		return this.each(function(i){
			var t = this;
			
			t.$this = $(this, i);
			t.$carousel = t.$this.children("ul, ol");
			t.$slides = t.$carousel.children();
			
			if (t.$slides.length < opts.shift+1) {
				//console.log('ERROR: Too few slides');t.$this.addClass("failed");return;
			} else t.$this.addClass("success");
			
			init(t);
		});
		
		function init(t){
			var $this = t.$this, $carousel = t.$carousel, $slides = t.$slides;
			
			if(opts.onInit) opts.onInit.call(this, $this);
			var $wrapper = $this.addClass(opts.loaderClass).wrapInner('<div />').children("div").css("opacity", 0);

			//====CONFIGURE CAROUSEL opts
			if(opts.cyclic){
				$carousel.append($slides.filter(":first").clone());
				$carousel.prepend($slides.filter(":last").clone());
				
				$slides = t.$slides = $carousel.children();
				opts.start += opts.shift;
			}
			
			t.running = false;
			t.curr = opts.start;
			
			//====SETUP CAROUSEL ELEMENTS
			//ul li
			$slides.css({"float": "left"});
			var w = t.slideWidth = getWidth($slides),
				l = t.slideLength = $slides.length;

			//.carousel
			$this.css({"overflow": "hidden"});
			
			//ul
			$carousel.css({"position": "relative", "left": -(w*t.curr), "top": 0, "overflow": "hidden", "width" : w*$slides.length});
			
			if(opts.fade) $carousel.before($carousel.clone().css("position", "absolute"));
			
			//====CONFIGURE CAROUSEL CONTROLS
			//PAGER
			if(opts.pager != null){
				for(var i=l;i--;){
					var link = document.createElement('a');
					link.setAttribute('href', '#');
					link.innerHTML = "<span>"+ (i+1)+"</span>";
					
					var img = new Image();
					img.src=$slides.eq(i).find("img")[0].src;
					link.appendChild(img);
					$(opts.pager).prepend(link);
				}
				
				//PAGER CURSOR
				var $pager = t.$pager = $(opts.pager);
				var $pagerLinks = t.$pagerLinks = $pager.children();
				$pager.append('<div class="cursor"><span class="left_c"/><span class="right_c" /></div>');
				
				t.pagerXpos = $pager.children(":first").addClass(opts.activeClass).position().left;
				var $cursor = $pager.find(".cursor").css({"position": "absolute", "left": t.pagerXpos, "width": $pager.children(":first").outerWidth()})
				t.pagerWidth = getWidth($pager.children(":first"));
			}
			
			//PAGER
			if(opts.pager != null)
				$.each($pagerLinks, function(i, el) {
					$(el).click(function() {
						clearInterval(t.timer);
						t.timer = null;
						return go(t, opts.cyclic ? opts.visible+i : i);
					});
				});
			
			//PREV
			if(opts.btnPrev)
				$(opts.btnPrev).click(function() {
					clearInterval(t.timer);
					t.timer = null;
					return go(t, t.curr-opts.shift);
				});
			
			//NEXT
			if(opts.btnNext)
				$(opts.btnNext).click(function() {
					clearInterval(t.timer);
					t.timer = null;
					return go(t, t.curr+opts.shift);
				});
			
			//GOTO
			if(opts.btnGo)
				$.each(opts.btnGo, function(i, el) {
					$(el).click(function() {
						clearInterval(t.timer);
						t.timer = null;
						return go(t, opts.cyclic ? opts.visible+i : i);
					});
				});
			
			//MOUSEWHEEL
			if(opts.mousewheel && $carousel.mousewheel)
				$carousel.mousewheel(function(e, k) {
					clearInterval(t.timer);
					t.timer = null;
					return k > 0 ? go(t, t.curr+opts.shift) : go(t, t.curr-opts.shift);
				});
			
			$slides.eq(t.curr).addClass(opts.activeClass);
			if(opts.onInitComplete) opts.onInitComplete.call($this);

			$wrapper.animate({"opacity": 1}, 800, function(){
				$wrapper.children().unwrap().parent().removeClass(opts.loaderClass);

				if(opts.auto){
					t.timer = setTimer(t, opts);

					$carousel.hover(function(e){
						clearInterval(t.timer);
						t.timer = null;
						t.hover = true;
					}, function(e){
						t.hover = false;
						t.timer = setTimer(t, opts);
					})
				};
			});
		};
		
		//Carousel engine(controller)
		function go(t, to){
			if(!t.running) {
				if(opts.onBeforeTransition) opts.onBeforeTransition.call(this, t.curr, to);
				
				if(to < 0){
					if(opts.cyclic){t.$carousel.css("left", ((t.slideLength-2)*t.slideWidth)*-1);t.curr = t.slideLength-3;}
					else{
						var mod = t.slideLength%opts.shift;
						t.curr = (t.slideLength - [(+mod) ? mod : opts.shift]);
					}
				}
				else if(to > t.slideLength-1){
					if(opts.cyclic){t.$carousel.css("left", t.slideWidth*-1);t.curr = 2;}
					else t.curr = 0;
				}
				else t.curr = to;

				t.running = true;
				
				if(opts.fade){
					t.$this.children("ul, ol").eq(0).css({"left": (t.curr*t.slideWidth)*-1});
					t.$this.children("ul, ol").eq(1).animate({"opacity": 0}, opts.speed, opts.easing, function(){
						if(opts.onAfterTransition) opts.onAfterTransition.call(this, t.curr);
						$(this).prependTo(t.$this).css("opacity", 1);
						if(opts.auto && typeof t.timer != "number") t.timer = setTimer(t, opts);
						t.running = false;
					});
				}
				else{
					t.$carousel.animate({"left" : (t.curr*t.slideWidth)*-1}, opts.speed, opts.easing, function(){
						t.$slides.removeClass(opts.activeClass).eq(t.curr).addClass(opts.activeClass);
						if(opts.onAfterTransition) opts.onAfterTransition.call(this, t.curr);
						if(opts.auto && typeof t.timer != "number") t.timer = setTimer(t, opts);
						t.running = false;
					});
					if(opts.pager != null)t.$pager.find(".cursor").animate({"left" : ((t.curr*t.pagerWidth)+t.pagerXpos)*1}, opts.speed, opts.easing, function(){
						t.$pagerLinks.removeClass(opts.activeClass).eq(t.curr).addClass(opts.activeClass);
					});
				}
			};

			return false;
		}
		
		function getWidth($el){return $el.outerWidth() + parseInt($el.css("marginLeft"), 10) + parseInt($el.css("marginRight"), 10);}
		function setTimer(t, opts){
			//safeguard to prevent multiple instances of the timer from being instantied and stacked under the same reference
			if(typeof t.timer == "number"){
				clearInterval(t.timer);
				t.timer = null;
			}

			if(typeof t.timer != "number" && !t.hover)return setInterval(function(){go(t, t.curr+opts.shift)}, opts.delay);
		}
	};
	
})(jQuery);
