/*
 * jQuery scroller plugin
 * - Will bind to any element and scroll through its children on next/prev click
 *
 *
*/

// $('ul').scroller();

(function($) {

    $.fn.scroller = function(options) {

        var $cont,
            nextItem = 0,
            childWidths = [],
            disabledClass = 'disabled',
            opts = handleOptions(options);

        function handleOptions(opts) {

            if (opts === undefined || opts === null)
                options = opts = $.fn.scroller.defaults;

            if (opts.constructor === Number)
                options = opts = { scroll : opts };

            opts = $.extend({}, $.fn.scroller.defaults, opts);

            opts.forward = opts.forward ? $(opts.forward) : $('<span class="btn-forward">Next</span>');
            opts.backward = opts.backward ? $(opts.backward) : $('<span class="btn-backward">Previous</span>');

            return opts;

        };

        function prepareScroller() {

            var cw, w = 0;

            $cont.children().each(function() {
                $(this).css('float', 'left');
                cw = $(this).outerWidth(true);

                childWidths.push(cw);
                w += cw;
            });

            $cont.wrap($('<div style="overflow: hidden"></div>'));

            $cont.css({
                'width': w + 'px',
                'overflow': 'hidden', /* clear fix */
                'position': 'relative'
            });

            /* append scroll buttons after scroller wrapper */
            $cont.parent().after(opts.forward).after(opts.backward);
        };

        function go(forward) {

            var scrollTo, remainder;
            var position = $cont.css('left');

            if (position == 'auto') position = '0px';
            position = parseInt(position.replace('px', ''), 10);

            opts.scroll = 0;

            if (forward) {

                for (i=0; i < options.scroll; i++) {
                    opts.scroll += childWidths[nextItem];
                    nextItem+=1;
                }

                scrollTo = position - opts.scroll;
                remainder = $cont.outerWidth() - (Math.abs(position) + $cont.parent().outerWidth());

                if (remainder < opts.scroll) {
                    scrollTo = position - remainder;
                    nextItem = $cont.children().length;
                }

            } else {
                nextItem-=1;

                for (i=0; i < options.scroll; i++) {
                    opts.scroll += childWidths[nextItem];
                    nextItem-=1;
                }

                scrollTo = position + opts.scroll;

                if (scrollTo > 0)
                    scrollTo = nextItem = 0;

            }

            /* scroll animation */
            if ($cont.is(':animated') === false) {
                $cont.animate(
                    {'left': scrollTo + 'px'},
                    {queue: false, duration: opts.speed},
                    updateButtonState(scrollTo)
                );
            }

        };

        function updateButtonState(scrollTo) {

            scrollTo = scrollTo || 0;

            var fwDisabled = opts.forward.hasClass(disabledClass),
                bkDisabled = opts.backward.hasClass(disabledClass),
                remainder = ($cont.outerWidth()-Math.abs(scrollTo));

            /* enable forward button */
            if (remainder > opts.scroll && fwDisabled)
                opts.forward.removeClass(disabledClass);

            /* disable forward button */
            if ((remainder <= $cont.parent().outerWidth()) && !fwDisabled)
               opts.forward.addClass(disabledClass);

            /* enable backward button */
            if (scrollTo < 0 && bkDisabled)
                opts.backward.removeClass(disabledClass);

            /* disable backward button */
            if (scrollTo === 0 && !bkDisabled)
                opts.backward.addClass(disabledClass);

        }

        return this.each(function() {

            $cont = $(this);

            /* style scroller and append buttons */
            prepareScroller();

            /* bind click event to forward button */
            opts.forward.bind('click', function(e) {
                if ($(this).hasClass(disabledClass) === false)
                    go(1);

                e.preventDefault();
            });

            /* bind click event to backward button */
            opts.backward.bind('click', function(e) {
                if ($(this).hasClass(disabledClass) === false)
                    go(0);

                e.preventDefault();
            });

            /* update scrollbar button state as necessary */
            updateButtonState();

        });
    };

    $.fn.scroller.defaults = {
        scroll: 4,                      // number of elements to scroll at a time
        speed: 600,                     // speed of scroll in miliseconds
        forward: null,                  // markup for button to scroll forward
        backward: null                  // markup for button to scroll backward
    };

})(jQuery);