﻿(function ($) {
    $.fn.carousel = function (options) {
        return this.each(function () {
            new $.carousel(this, options);
        });
    };

    var defaults = {
        index: 1,
        auto: true,
        scroll: 0,
        animation: 500,
        delay: 10000,
        circular: true,
        changeCallBack: null
    };

    $.carousel = function (element, options) {
        var base = this;

        base.element = element;
        base.$element = $(element);

        // Set up a few defaults
        base.index = -1;
        base.timer = null;

        // Add a reverse reference to the DOM object
        base.$element.data("carousel", this);

        base.$container = base.$element.find("ul:first");

        // Init function
        base.init = function () {
            base.$container.parent().css({ overflow: "hidden", position: "relative" });
            base.$container.css({ position: "absolute" });

            base.options = $.extend({}, defaults, options);

            if (!base.options.animation) base.options.animation = 500;

            // set variables
            base.busy = false;
            base.count = base.$container.find("li").length;
            base.itemWidth = base.$container.find("li").outerWidth();
            base.perPage = Math.round(base.$container.width() / ((base.itemWidth > 0) ? base.itemWidth : 1));
            base.width = (base.count - base.perPage) * base.itemWidth;

            if (!base.options.scroll) base.options.scroll = base.perPage;

            // set timer
            base.timer = null;
            base.playing = false;

            if ((base.options.navigation == true) || (base.options.circular == true)) {
                // clone first and last
                var first = base.$container.find("li:first");
                var last = base.$container.find("li:last");

                for (var i = 0; i < base.perPage; i++) {
                    $(last).clone().addClass("clone").insertBefore(base.$container.find("li:first"));
                    $(first).clone().addClass("clone").insertAfter(base.$container.find("li:last"));

                    first = $(first).next();
                    last = $(last).prev();
                }
            }

            base.clones = base.$container.find("li.clone").length / 2;

            // bind scroll buttons
            base.$prev = base.$element.find("a.carousel-prev");

            if ((base.$prev.length == 0) && (base.$container.find("li").length > base.perPage)) {
                base.$prev = $('<a href="javascript:void(0)"></a>').addClass("carousel-prev");

                base.$element.append(base.$prev);
            }

            base.$prev.click(function (e) {
                base.scroll(-1, false);
            });

            base.$next = base.$element.find("a.carousel-next");

            if (base.$next.length == 0) {
                base.$next = $('<a href="javascript:void(0)"></a>').addClass("carousel-next");

                base.$element.append(base.$next);
            }

            base.$next.click(function (e) {
                base.scroll(1, false);
            });

            if (base.count <= base.perPage) {
                base.$prev.hide();
                base.$next.hide();
            }

            // set ul width
            base.$container.width(base.$container.find("li").length * base.itemWidth);

            // select 
            if (base.options.index)
                base.goto(base.options.index - 1 + base.clones, false);
            else
                base.goto(base.clones, false);

            // start auto scroll
            if (base.options.auto == true) {
                if (!base.options.delay) base.options.delay = 3000;
                if (base.options.delay < 1000)
                    base.options.delay *= 1000;

                base.startStop(true);
            }
        };

        // Go to slide
        base.goto = function (index, animate, autoplay) {
            if (((base.clones == 0) && (base.index != -1)) && ((index < base.clones) || (index + base.perPage > base.count)))
                return;

            // Positioning Carousel before animation
            if ((animate == true) && (base.busy == false)) {
                var direction = (index > base.index) ? 1 : -1;

                if (base.options.circular == true) {
                    if ((base.index + base.perPage) * direction >= base.count + base.clones) {
                        base.index -= base.count;
                        index = base.index + base.perPage;
                    }
                    if ((base.index <= base.clones) && (direction < 0)) {
                        base.index += base.count;
                        index = base.index - base.perPage;
                    }
                }

                base.goto(base.index, false);
            }

            if ((autoplay == false) && (base.playing == true))
                base.startStop(false);

            var left = 0 - base.$container.position().left;

            if (left != base.itemWidth * index)
                if (animate == true)
                    base.$container.animate({
                        left: (0 - (base.itemWidth * index))
                    }, base.options.animation);
                else
                    base.$container.css({ left: (0 - (base.itemWidth * index)) });

            if (base.options.circular !== true)
                if (index + base.perPage >= base.count) {
                    base.$next.addClass("disabled");
                    base.$prev.removeClass("disabled");
                }
                else if (index <= 0) {
                    base.$prev.addClass("disabled");
                    if (base.count > base.perPage)
                        base.$next.removeClass("disabled");
                }

            if (base.index != index) {
                base.index = index;

                // Call On Chage Callback
                if (base.options.changeCallBack != null)
                    base.options.changeCallBack(base.element, index, (index + base.perPage == base.count));
            }
        };

        // Scroll
        base.scroll = function (direction, autoplay) {
            var newIndex = base.index + (base.options.scroll * direction);

            if ((newIndex < base.count) && (newIndex + base.perPage > base.count) && (base.options.circular !== true))
                newIndex = base.count - base.perPage;

            if ((newIndex < 0) && (base.index > 0) && (base.options.circular !== true))
                newIndex = 0;

            base.goto(newIndex, true, autoplay);
        };

        // Timer
        base.startStop = function (playing) {
            if (playing !== true) playing = false; // Default if not supplied is false

            // Update variable
            base.playing = playing;

            if (playing) {
                base.clearTimer(); // Just in case this was triggered twice in a row

                base.timer = window.setInterval(function () {
                    base.scroll(1, true);
                }, base.options.delay);
            } else {
                base.clearTimer();
            };
        };

        base.clearTimer = function () {
            // Clear the timer only if it is set
            if (base.timer) window.clearInterval(base.timer);
        };

        // Trigger the initialization
        base.init();
    };
})(jQuery);
