(function($) {                                          // Compliant with jquery.noConflict()
$.fn.jCarouselLite = function(o) {
    o = $.extend({
        btnPrev: null,
        btnNext: null,
        btnGo: null,
        mouseWheel: false,
        auto: null,

        speed: 200,
        easing: null,

        vertical: false,
        circular: true,
        visible: 3,
        start: 0,
        scroll: 1,

        beforeStart: null,
        afterEnd: null
    }, o || {});

    return this.each(function() {                           // Returns the element collection. Chainable.

        var $running = false, $animCss=o.vertical?'top':'left', $sizeCss=o.vertical?'height':'width';
        var $div = $(this), $line = $('.line', $div), $tUnit = $('.unit', $line), $tu = $tUnit.size(), $v = o.visible;

        if(o.circular) {
            $line.prepend($tUnit.slice($tu-$v-1+1).clone())
              .append($tUnit.slice(0,$v).clone());
            o.start += $v;
        }

        var $unit = $('.unit', $line), $itemLength = $unit.size(), curr = o.start;
        $div.css('visibility', 'visible');

        $unit.css({overflow: 'hidden', float: o.vertical ? 'none' : 'left'});
        $line.css({margin: '0', padding: '0', position: 'relative', 'list-style-type': 'none', 'z-index': '1'});
        $div.css({overflow: 'hidden', position: 'relative', 'z-index': '2', left: '0px'});

        var $unitSize = o.vertical ? height($unit) : width($unit); // Full $unit size(incl margin)-Used for animation
        var $lineSize = $unitSize * $itemLength;                   // size of full $line(total length, not just for the visible items)
        var $divSize = $unitSize * $v;                             // size of entire $div(total length for just the visible items)

        $unit.css({width: $unit.width(), height: $unit.height()});
        $line.css($sizeCss, $lineSize+'px').css($animCss, -(curr*$unitSize));

        $div.css($sizeCss, $divSize+'px');                         // Width of the DIV. length of visible images

        if(o.btnPrev)
            $(o.btnPrev).click(function() {
                return go(curr-o.scroll);
            });

        if(o.btnNext)
            $(o.btnNext).click(function() {
                return go(curr+o.scroll);
            });

        if(o.btnGo)
            $.each(o.btnGo, function(i, val) {
                $(val).click(function() {
                    return go(o.circular ? o.visible+i : i);
                });
            });

        if(o.mouseWheel && $div.mousewheel)
            $div.mousewheel(function(e, d) {
                return d>0 ? go(curr-o.scroll) : go(curr+o.scroll);
            });

        if(o.auto)
            setInterval(function() {
                go(curr+o.scroll);
            }, o.auto+o.speed);

        function vis() {
            return $unit.slice(curr).slice(0,$v);
        };

        function go(to) {
            if(!$running) {

                if(o.beforeStart)
                    o.beforeStart.call(this, vis());

                if(o.circular) {            // If circular we are in first or last, then goto the other end
                    if(to<=o.start-$v-1) {           // If first, then goto last
                        $line.css($animCss, -(($itemLength-($v*2))*$unitSize)+'px');
                        // If 'scroll' > 1, then the 'to' might not be equal to the condition; it can be lesser depending on the number of elements.
                        curr = to==o.start-$v-1 ? $itemLength-($v*2)-1 : $itemLength-($v*2)-o.scroll;
                    } else if(to>=$itemLength-$v+1) { // If last, then goto first
                        $line.css($animCss, -( ($v) * $unitSize ) + 'px' );
                        // If 'scroll' > 1, then the 'to' might not be equal to the condition; it can be greater depending on the number of elements.
                        curr = to==$itemLength-$v+1 ? $v+1 : $v+o.scroll;
                    } else curr = to;
                } else {                    // If non-circular and to points to first or last, we just return.
                    if(to<0 || to>$itemLength-$v) return;
                    else curr = to;
                }                           // If neither overrides it, the curr will still be 'to' and we can proceed.

                $running = true;

                $line.animate(
                    $animCss == 'left' ? { left: -(curr*$unitSize) } : { top: -(curr*$unitSize) } , o.speed, o.easing,
                    function() {
                        if(o.afterEnd)
                            o.afterEnd.call(this, vis());
                        $running = false;
                    }
                );
                // Disable buttons when the carousel reaches the last/first, and enable when not
                if(!o.circular) {
                    $(o.btnPrev + ',' + o.btnNext).removeClass('disabled');
                    $( (curr-o.scroll<0 && o.btnPrev)
                        ||
                       (curr+o.scroll > $itemLength-$v && o.btnNext)
                        ||
                       []
                     ).addClass('disabled');
                }

            }
            return false;
        };
    });
};

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);

