//2009 Manuel van Dyck & Stan Chow
(function ( $ ) {                // Compliant with jquery.noConflict()
$.fn.ProductCarousel = function(o) {   

    o = $.extend({
        ms_interval: 500,		// speed in ms of the animation.                        
        visible: '100%',		// size of the carousel on the screen. Can be in percent '100%', in pixels '100px', or in images '3' (for 3 images)
        start: 0,				// position in pixels that the carousel shall start at        
        step: "default"			// value in pixels, or "default"        
    }, o || {});
	
    return this.each(function() {                           // Returns the element collection. Chainable.   
		        		
        var div = $(this), ul = $("ul", div), tLi = $("li", ul), tl = tLi.size(), v = o.visible;
		var cssU = (v.toString().indexOf("%") != -1 ? '%' : (v.toString().indexOf("px") != -1) ? 'px' : 'el');
		
        // circular mode management
        // we add at the end and at the beginning some fake images to make the circular effect more linear, so it never breaks
        // it is still possible to improve the memory management by adding exactly the number of images requested.        		
		var imgSet = tLi.clone();
        ul.prepend(imgSet).append(imgSet.clone());
                           
		var li = $("li", ul);								 	// list       
        div.css("visibility", "visible");
        li.css("overflow", "hidden")                       	// If the list item size is bigger than required
			.css("float", "left")     							// Horizontal list
            .children().css("overflow", "hidden");				// If the item within li overflows its size, hide'em
        li.css("display", "inline");								// IE double margin bug - rooo..
        if(li.children().get(0).tagName.toLowerCase() == 'a'){
        	li.children().css('float','left');
        }

        ul.css("margin", "0")                             	// Browsers apply default margin 
            .css("padding", "0")                          	// and padding. It is reset here.
            .css("position", "relative")                    		// IE BUG - width as min-width
            .css("list-style-type", "none")                 		// We dont need any icons representing each list item.
            .css("z-index", "1");                           	// IE doesnt respect width. So z-index smaller than div

        div.css("overflow", "hidden")                     		// Overflows - works in FF
            .css("position", "relative")                    		// position relative and z-index for IE
            .css("z-index", "2")                         		// more than ul so that div displays on top of ul
            .css("left", "0px");                          		// after creating carousel show it on screen
        
        var liSize = width(li);   							// Full li size(incl margin)-Used for animation
        var liSizeV = height(li);							// size of the main layer, in its side          
        var curr = o.start;   								// Current position in pixels  
        var nbAllElts = li.size();							// Total number of items  
        var ulSize = liSize * nbAllElts;                   	// size of full ul(total length, not just for the visible items)
        var nbElts = tl;									// number of elements (only visible items)
        var eltsSize = nbElts * liSize;						// size of the visible elements only
        var allEltsSize = nbAllElts * liSize;				// Total size of the elements        
        var step = o.step == 'default' ? liSize : o.step;	// step size
              																		
        // Adjust the start position in case of circular mode
        o.start += (liSize * tl);  							// The start position is one carousel length ahead due to the optical effect
        curr += (liSize * tl);								// used for the animation
                
        // Calculates the size of the main div according to the given size (can be in percent, in value or in pixels)
        var divSize, cssSize, cssUnity;
        if(cssU == '%'){									// in percent 
        	divSize = 0;									// We don't have the value in pixels unless we set the percent value first. So 0, and will catch it later
        	cssSize = parseInt(v);  
       		cssUnity = "%";
        }
        else if(cssU == 'px'){								// in pixels
        	divSize = parseInt(v);
        	cssSize = parseInt(v);
        	cssUnity = "px";
        }
        else{												// in elements (number of elements to display)
        	divSize = liSize * parseInt(v);
        	//BLEH!
        	cssSize = liSize * parseInt(v);
        	cssSize = 643;
        	cssUnity = "px";
        }                      								  

        ul.css("width", ulSize + "px")                      	// Width of the UL is the full length for all the images
          .css("left", -(o.start));	                  	 	// Set the starting item
        div.css("width", cssSize + cssUnity);              	// Width of the DIV. length of visible images
        
		if(divSize === 0){									// We didn't have the size in pixels in case of % size. Catch up !
			divSize = div.width();							// The size is simply the calculated size in pixels
		}
		
		// horizontal mode
		div.css('height', liSizeV + 'px');
		ul.css('height', liSizeV + 'px');	
										
		// calculate the number of visible elements inside (in case of size in percent)							
		if(cssU == '%'){
			v = divSize / li.width();						
			if(v % 1 !== 0){ v +=1; }
			v = parseInt(v);
		}
				
		// bind the events
		div.bind('mouseout', function() { return forward(); });
		div.bind('mouseover',function() { return stop(); });
        
		// start the animation!		
	   	forward();	
	   		
		// setup tooltips
		$(".produkt_tooltip").hover(function(e) {							
			$('#tooltip_wrapper').stop(true, true)
			.html($(this).find("div")[0].innerHTML)
			.css({top:e.pageY + "px", left: e.pageX - 750 +"px"})
			.fadeIn(250);
			
		}, function() {					
			$('#tooltip_wrapper').fadeOut(600);	
		});
		
		// animate the track by moving it forward according to the step size and the speed		 
        function forward(){
    		ul.animate( { left: -(curr + step) } , o.ms_interval, 'linear',				
                function() {
                	curr += step; //Add step size
					
                	//calculate whether we cross the limit,
                	//if so, put the carousel one time backward                	
	                if(curr + divSize + liSize >= allEltsSize) {
	                   	ul.css('left', -curr + eltsSize);
	                   	curr -= eltsSize;	                
                	}    				
                    forward();
                }
            );						
        }
        
        //stops the animation
        function stop(){        	
        	ul.stop(true,false); 				// stop the animation straight
        	curr = 0 - parseInt(ul.css("left"));	// we stopped suddenly, so the curr variable is not refreshed. We refresh it with the true value        	        	
        }        
    });
};

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);
