/* 
 * 
 * JMyCarousel is inspired and based on JCarouselLite, an original concept by Ganeshji Marwaha
 * $LastChangedDate: 2007-06-22 20:08:34 -0500 (Thu, 22 Nov 2007) $
 * Custom Edition 11/01/2011
 * 
 */

(function ( $ ) {

	$.fn.jMyCarousel = function(o) {   


		o=$.extend({btnPrev:null, btnNext:null, mouseWheel:true, auto:true, speed:1000,hover_speed:200,easing:'linear',vertical:false,circular:true,visible:'5',start:0,scroll:1,step:50,eltByElt:false,evtStart:'mouseover',evtStop:'mouseout',beforeStart:null,afterEnd:null},o||{});

/*

		o = $.extend({
			btnPrev: null,			// previous button customization
			btnNext: null,			// next button customization
			mouseWheel: true,
			auto: true,

			speed: 1000,
			hover_speed: 200,
			easing: 'linear',
			stopOnLi: true,

			vertical: false,
			circular: true,
			visible: '900px',
			start: 0,
			scroll: 1,
		
			step: 50,
			eltByElt: false,
		}, o || {});

*/

		return this.each(function() {
			var running = false, animCss=o.vertical?"top":"left", sizeCss=o.vertical?"height":"width";
			var div = $(this), ul = $("ul", div), tLi = $("li", ul), tl = tLi.size(), v = o.visible;
			var mousewheelN = 0;
			var defaultBtn = (o.btnNext === null && o.btnPrev === null) ? true : false;
			var cssU = (v.toString().indexOf("%") != -1 ? '%' : (v.toString().indexOf("px") != -1) ? 'px' : 'el');
			var direction = null;

			if(o.circular) {
					var imgSet = tLi.clone();
			    ul.prepend(imgSet).append(imgSet.clone());
			}
				   
			var li = $("li", ul);
			div.css("visibility", "visible");
			li.css("overflow", "hidden")
			    .css("float", o.vertical ? "none" : "left")
			    .children().css("overflow", "hidden");
			if(!o.vertical){ li.css("display", "inline"); }
			if(li.children().get(0).tagName.toLowerCase() == 'a' && !o.vertical){
				li.children().css('float','left');
			}
			if(o.vertical && jQuery.browser.msie){
				li.css('line-height', '4px').children().css('margin-bottom', '-4px');
			}
		
			ul.css("margin", "0")
			    .css("padding", "0")
			    .css("position", "relative")
			    .css("list-style-type", "none")
			    .css("z-index", "1");

			div.css("overflow", "hidden")
			    .css("position", "relative")
			    .css("z-index", "2")
			    .css("left", "0px");
		
			var liSize = o.vertical ? height(li) : width(li);
			var liSizeV = o.vertical ? elHeight(li) : height(li);
			var curr = o.start;
			var nbAllElts = li.size();
			var ulSize = liSize * nbAllElts;
			var nbElts = tl;
			var eltsSize = nbElts * liSize;
			var allEltsSize = nbAllElts * liSize;
			var step = o.step == 'default' ? liSize : o.step;
			o.btnPrev = defaultBtn ? $('<input type="button" class="' + (o.vertical ? 'up' : 'prev') + '" />') : $(o.btnPrev);
			o.btnNext = defaultBtn ? $('<input type="button" class="' + (o.vertical ? 'down' : 'next') + '" />') : $(o.btnNext);
			var prev = o.btnPrev;
			var next = o.btnNext;
		
			if(defaultBtn && o.auto !== true){
				prev.css({'opacity':'0.9'});
				next.css({'opacity' :'0.9'});
				div.prepend(prev);
				div.prepend(next);
				o.btnPrev = prev;
				o.btnNext = next;
			}

			if(o.eltByElt){ 
				step = liSize;
				if(o.start % liSize !== 0){
					var imgStart = parseInt(o.start / liSize);
					curr = o.start = (imgStart * liSize);
				}
			}
		
			if(o.circular){
				o.start += (liSize * tl);
				curr += (liSize * tl);
			}

			var divSize, cssSize, cssUnity;
			if(cssU == '%'){
				divSize = 0;
				cssSize = parseInt(v);  
		       		cssUnity = "%";
			}
			else if(cssU == 'px'){
				divSize = parseInt(v);
				cssSize = parseInt(v);
				cssUnity = "px";
			} else {
				divSize = liSize * parseInt(v); 
				cssSize = liSize * parseInt(v);
				cssUnity = "px";
			}                      								  

			ul.css(sizeCss, ulSize + "px")
				.css(animCss, -(o.start));
			div.css(sizeCss, cssSize + cssUnity);
			if(o.vertical && cssUnity == '%'){
				var pxsize = ((liSize * nbElts) * (parseInt(v) / 100));
				div.css(sizeCss,  pxsize + 'px');
			}

			if(divSize === 0){
				divSize = div.width();
			}

			if(o.vertical){
				div.css("width" , liSizeV + 'px');
				ul.css("width", liSizeV + 'px');
				li.css('margin-bottom', (parseInt(li.css('margin-bottom')) * 2) + 'px');
				li.eq(li.size() - 1).css('margin-bottom', li.css('margin-top'));
			}else{
				div.css('height', liSizeV + 'px');
				ul.css('height', liSizeV + 'px');	
			}

			if(cssU == '%'){
				v = divSize / li.width();						
				if(v % 1 !== 0){ v +=1; }
				v = parseInt(v);
			}

			var divVSize = div.height();

			if(defaultBtn){
				next.css({'z-index':200, 'position':'absolute'});
				prev.css({'z-index':200, 'position':'absolute'});

				if(o.vertical){
					prev.css({'width': prev.width(), 'height' : prev.height(), 'top' : '0px', 'left': parseInt(liSizeV / 2) - parseInt(prev.width() / 2) + 'px'});
					next.css({'width': prev.width(), 'height' : prev.height(), 'top' : (divVSize - prev.height()) + 'px', 'left' : parseInt(liSizeV / 2) - parseInt(prev.width() / 2) + 'px'});
				}else{
					prev.css({'left':'0px', 'top': parseInt(liSizeV / 2) - parseInt(prev.height() / 2) + 'px'});
					next.css({'right':'0px', 'top': parseInt(liSizeV / 2) - parseInt(prev.height() / 2) + 'px'});
				}
			}

			if(o.btnPrev){            
				$(o.btnPrev).bind('click', function() {
					if(defaultBtn){ o.btnPrev.css('opacity',0.9); }
					stop();
					speed = o.speed;
					running = true;
					direction = 'backward';
					return backward(step, false, speed); 
				})
				.bind('mouseover', function() {
					if(defaultBtn){ o.btnPrev.css('opacity',0.9); }
					stop();
					speed = o.hover_speed;
					running = true;
					direction = 'backward';
					return backward(step, false, speed); 
				}).bind('mouseout', function() {
					if(defaultBtn){ o.btnPrev.css('opacity',0.9); }
					stop();
					speed = o.speed;
					running = true;
					direction = 'backward';
					return backward(step, false, speed); 
				});
			}

			if(o.btnNext){
				$(o.btnNext).bind('click', function() {
					if(defaultBtn){ o.btnNext.css('opacity',0.9); }
					stop();
					speed = o.speed;
					running = true;
					direction = 'forward';
					return forward(step, false, speed); 
			    	})
				.bind('mouseover', function() {
					if(defaultBtn){ o.btnNext.css('opacity',0.9); }
					stop();
					speed = o.hover_speed;
					running = true;
					direction = 'forward';
					return forward(step, false, speed); 
				})
				.bind('mouseout', function() {
					if(defaultBtn){ o.btnNext.css('opacity',0.9); }
					stop();
					speed = o.speed;
				 	running = true;	
					direction = 'backward';
				  	return backward(step, false, speed); 
				});
			}

			if(o.stopOnLi){
				div.find('li').bind('mouseout', function() {
				 	running = true;	
					direction = 'backward';
				  	backward();
			    	})
				.bind('mouseover',function() {
					return stop(); 
				});
			}

			if(o.auto === true){
			 	running = true;	
				direction = 'backward';
			  	backward();
			}

			function forward(stepsize, once, speed){
		    		var s = (stepsize ? stepsize : step);
				speed = (speed ? speed : o.speed);

				if(running === true && direction === "backward"){ return; }

		    		if(!o.circular){
		    			if(curr + s + (o.vertical ? divVSize : divSize) > eltsSize){
		    				s = eltsSize - (curr + (o.vertical ? divVSize : divSize));
		    			}
		    		}

		    		ul.animate(
					animCss == "left" ? { left: -(curr + s) } : { top: -(curr + s) } , speed, o.easing,
					function() {
						curr += s;
						if(o.circular){
							if(curr + (o.vertical ? divVSize : divSize) + liSize >= allEltsSize){
							    	ul.css(o.vertical ? 'top' : 'left', -curr + eltsSize);
							    	curr -= eltsSize;
							}
						}
						forward(stepsize, once, speed);
					}
				);
			}

			function backward(stepsize, once, speed){
				var s = (stepsize ? stepsize : step);
				speed = (speed ? speed : o.speed);

				if(running === true && direction === "forward"){ return; } 

				if(!o.circular){
					if(curr - s  < 0){
						s = curr - 0;
					}
				}

				ul.animate(
					animCss == "left" ? { left: -(curr - s) } : { top: -(curr - s) } , speed, o.easing,
					function() {
						curr -= s;
						if(o.circular){
							if(curr <= liSize){
								ul.css(o.vertical ? 'top' : 'left', -(curr + eltsSize));
								curr += eltsSize;
							}
						}
						backward(stepsize, once, speed);
					}
				);
			}

			function stop(){
				if(!o.eltByElt){
					ul.stop();
					curr = 0 - parseInt(ul.css(animCss));
				}
				running = false;
				direction = null;
			}

			function imgSize(el, dimension){
				if(dimension == 'width'){
					return el.find('img').width();
				}
				else {
					return el.find('img').height();
				}
			}

			function elHeight(el){
				var elImg = el.find('img');
				if(o.vertical){
				    	return parseInt(el.css('margin-left')) 
						+ parseInt(el.css('margin-right')) 
						+ parseInt(elImg.width()) 
						+ parseInt(el.css('border-left-width')) 
						+ parseInt(el.css('border-right-width')) 
						+ parseInt(el.css('padding-right')) 
						+ parseInt(el.css('padding-left'));
				} else {
					return parseInt(el.css('margin-top')) 
						+ parseInt(el.css('margin-bottom')) 
						+ parseInt(elImg.width()) 
						+ parseInt(el.css('border-top-height')) 
						+ parseInt(el.css('border-bottom-height')) 
						+ parseInt(el.css('padding-top')) 
						+ parseInt(el.css('padding-bottom'));
				}
			}

			function debug(html){
				$('#debug').html($('#debug').html() + html + "<br/>");
			} 
		});
	};

	function css(el, prop) {
		return parseInt($.css(el[0], prop)) || 0;
	}

	function width(el) {
		return el[0].offsetWidth + css(el, 'marginLeft') + css(el, 'marginRight');
	}

	function height(el) {
		return el[0].offsetHeight + css(el, 'marginTop') + css(el, 'marginBottom');
	}
})(jQuery);

