(function ($) {
    var methods = {
        init: function (options) {
            var settings = {
                speed: 4000,
                navigation: true,
                auto: true
            };
            return this.each(function () {
                if (options) {
                    $.extend(settings, options);
                }
                var items = $(this).find("li");
                var variables = {
                    self: $(this),
                    slides: items,
                    upperLimit: items.length,
                    current: 0,
                    next: 1,
                    currentStep: -1,
                    interrupted: false
                }
                variables.self.addClass("slider");
                if (settings.navigation) {
                    methods.buildNavigation(variables, settings, variables.self.find("li").length);
                    variables.navs = $(this).find("div.sliderNav a.sliderControl");
                }
                settings.infoHeight = items.height();
                $(items[0]).find(">div").animate({
                    height: settings.infoHeight
                }, settings.speed / 2, function () {
                    if (settings.auto) {
                        variables.timer = setTimeout(function () {
                            methods.next(variables, settings)
                        }, settings.speed);
                    }
                });
            });
        },
        buildNavigation: function (variables, settings, size) {
            var nav = $("<div class='sliderNav'>");
            var items = "";
            for (var i = 0; i < size; i++) {
                items += "<a class='sliderControl";
                if (i == 0) {
                    items += " current";
                }
                items += "'></a>";
            };
            var nav = $("<div class='sliderNav'>" + items + "</div>");
            variables.self.append(nav);
            var navItems = nav.find("a");
            for (i = 0; i < size; i++) {
                $(navItems[i]).click(methods.handleNavClick(variables, settings, i));
            }
        },
        handleNavClick: function (variables, settings, pos) {
            return function () {
                methods.interruptShift(variables, settings, pos);
                return false;
            }
        },
        shiftTo: function (variables, settings, target) {
            if (variables.current != target) {
                clearTimeout(variables.timer);
                var current = $(variables.slides[variables.current]);
                var next = $(variables.slides[target]);
                variables.next = target;
                methods.closeSlide(current, next, variables, settings, target);
            }
        },
        closeSlide: function (current, next, variables, settings, target) {
            variables.currentStep = 0;
            current.find(">div").animate({
                height: 0
            }, settings.speed / 2, function () {
                methods.swapSlide(current, next, variables, settings, target);
            });
        },
        swapSlide: function (current, next, variables, settings, target) {
            variables.currentStep = 1;
            current.animate({
                opacity: 0
            }, settings.speed / 4);
            $(variables.navs[variables.current]).removeClass("current");
            $(variables.navs[target]).addClass("current");
            variables.current = target;
            next.animate({
                opacity: 1
            }, settings.speed / 4, function () {
                methods.openSlide(current, next, variables, settings, target);
            });
        },
        openSlide: function (current, next, variables, settings, target) {
            variables.currentStep = 2;
            next.find(">div").animate({
                height: settings.infoHeight
            }, settings.speed / 2, function () {
                variables.currentStep = -1;
                if (settings.auto) {
                    variables.timer = setTimeout(function () {
                        methods.next(variables, settings);
                    }, settings.speed);
                    variables.next = (variables.next + 1) % variables.upperLimit;
                }
            });
        },
        interruptShift: function (variables, settings, target) {
            if (variables.current != target) {
                clearTimeout(variables.timer);
                var current = $(variables.slides[variables.current]);
                var next = $(variables.slides[target]);
                variables.navs.removeClass("current");
                $(variables.navs[target]).addClass("current");
                variables.interrupted = true;
                switch (variables.currentStep) {
                    case 0:
                        var info = current.find(">div");
                        var h = info.height();
                        info.stop().animate({
                            height: 0
                        }, settings.speed / 2 * (h / settings.infoHeight), function () {
                            variables.next = target;
                            methods.swapSlide(current, next, variables, settings, target);
                        });
                        break;
                    case 1:
                        var oldTarget = $(variables.slides[variables.next]);
                        oldTarget.stop();
                        var opacity = parseFloat(oldTarget.css("opacity"));
                        oldTarget.css("opacity", 0);
                        variables.current = target;
                        next.css("opacity", opacity);
                        next.animate({
                            opacity: 1
                        }, (settings.speed / 2) * (1 - opacity), function () {
                            methods.openSlide(current, next, variables, settings, target);
                        });
                        break;
                    case 2:
                        var info = $(variables.slides[variables.current]).find(">div");
                        var h = info.height();
                        info.stop().animate({
                            height: 0
                        }, settings.speed / 2 * (h / settings.infoHeight), function () {
                            methods.swapSlide(current, next, variables, settings, target);
                        })
                        break;
                    default:
                        methods.shiftTo(variables, settings, target);
                }
            }
        },
        next: function (variables, settings) {
            if (variables.current + 1 == variables.upperLimit) {
                methods.shiftTo(variables, settings, 0);
            }
            else {
                methods.shiftTo(variables, settings, variables.current + 1);
            }
        }
    };

    $.fn.slider = function (method) {
        var variables;

        if (typeof method === 'object' || !method) {
            return methods.init.apply(this, arguments);
        } else {
            $.error('Method ' + method + ' does not exist on jQuery.tooltip');
        }
    }
})(jQuery);
