//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", "right")                                 // 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 = 568;
            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 - 150 + "px", left: e.pageX - 500 + "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);