/**
 
 * @author: tom.bran[]gmail-com
 
 * @version: 0.9.8
 
 * edited: August '10
 
 * plugin name: CarouSlide
 
 */

(function ($) {
    $.fn.CarouSlide = function (userConfig) {
        $.fn.CarouSlide.config = {
            slideTime: 5000,
            animTime: 1000,
            autoAnim: false,
            animInfinity: false,
            alwaysNext: false,
            animType: "fade",
            showSlideNav: true,
            showBackNext: false,
            showPauseButton: false,
            sliderHolder: ".slider-holder",
            navContainer: ".slider-nav",
            hoverLinks: false,
            easingStyle: null
        };

        function methods() {
            this.props = {};
            var $m = this;
            this.gotoSlide = function (pos, direct, dir) {
                pos = parseInt(pos);
                if (pos != $m.props.currentSlide) {
                    $m.props.animReady = false;
                    $m.props.prevSlide = $m.props.currentSlide;
                    $m.props.direction = dir;
                    $m.props.direct = direct;
                    $m.props.animQueue = null;
                    $m.props.oldPos = $m.props.currentSlide;
                    $m.props.newPos = null;
                    if ($m.props.direct) {
                        if ($m.props.autoAnim && $m.props.animState == "play") {
                            $m.resetTimer();
                        }

                        $m.props.currentSlide = pos;
                    }

                    else {
                        $m.props.currentSlide += dir;
                        if ($m.props.currentSlide >= $m.props.sCount) {
                            $m.props.currentSlide = pos = 0;
                        }

                        if ($m.props.currentSlide < 0) {
                            $m.props.currentSlide = pos = $m.props.sCount - 1;
                        }
                    }

                    if ($m.props.showSlideNav) {
                        $m.setNavActive($m.props.currentSlide);
                    }

                    switch ($m.props.animType) {
                    case "none":
                        newPos = $m.slideAnimSetup($m.props.sWidth, "left", pos);
                        $m.props.sUL.css({
                            "left": newPos + "px"
                        });
                        $m.props.direct = null;
                        $m.props.animReady = true;
                        break;
                    case "slide":
                        newPos = $m.slideAnimSetup($m.props.sWidth, "left", pos);
                        $m.props.sUL.animate({
                            "left": newPos + "px"
                        }, $m.props.animTime, $m.props.easingStyle, $m.transAnimCallback);
                        break;
                    case "slide-vertical":
                        newPos = $m.slideAnimSetup($m.props.sHeight, "top", pos);
                        $m.props.sUL.animate({
                            "top": newPos + "px"
                        }, $m.props.animTime, $m.props.easingStyle, $m.transAnimCallback);
                        break;
                    case "fade":
                        var $current = $m.props.sUL.find("> li:eq(" + $m.props.currentSlide + ")");
                        var $prev = $m.props.sUL.find("> li:eq(" + $m.props.prevSlide + ")");
                        $current.css("z-index", "100").animate({
                            "opacity": "1"
                        }, $m.props.animTime, $m.transAnimCallback);
                        $prev.css("z-index", "10");
                        if ($m.props.prevSlide !== null) {
                            setTimeout(function () {
                                $prev.css("opacity", "0");
                            }, $m.props.animTime);
                        }

                        break;
                    default:
                    }
                }
            };
            this.slideAnimSetup = function (dim, dir, pos) {
                var output;
                var minus = dir == "top" ? 0 : 1;
                if ($m.props.animInfinity) {
                    if ($m.props.direct) {
                        $m.resetAllSlidePositions();
                        $m.props.sUL.css(dir, -(dim * $m.props.oldPos) + "px");
                        output = -(dim * $m.props.currentSlide);
                    } else {
                        output = -dim + (dim * -$m.props.direction);
                    }
                } else if ($m.props.alwaysNext) {
                    $(".s-id-" + $m.props.oldPos, $m.props.sUL).remove().prependTo($m.props.sUL);
                    $(".s-id-" + $m.props.currentSlide, $m.props.sUL).remove().insertAfter($(".s-id-" + $m.props.oldPos, $m.props.sUL));
                    var listItem = $(".s-id-" + $m.props.oldPos, $m.props.sUL);
                    $m.props.sUL.css(dir, "0px");
                    output = ($m.props.sUL.css(dir).split("px")[0] - dim);
                }

                else {
                    output = (dim * -pos);
                }

                return output;
            };
            this.transAnimCallback = function () {
                if ($m.props.animInfinity) {
                    if ($m.props.direct) {
                        $m.setSlideOrder($m.props.currentSlide);
                    }

                    if ($m.props.direction == 1) {
                        var firstSlide = $(".slide:first", $m.props.sUL);
                        firstSlide.remove().appendTo($m.props.sUL);
                    }

                    else if ($m.props.direction == -1) {
                        var lastSlide = $(".slide:last", $m.props.sUL);
                        lastSlide.remove().prependTo($m.props.sUL);
                    }

                    if ($m.props.animType == "slide") {
                        $m.props.sUL.css("left", -$m.props.sWidth + "px");
                    }

                    if ($m.props.animType == "slide-vertical") {
                        $m.props.sUL.css("top", -$m.props.sHeight + "px");
                    }
                }

                $m.props.direct = null;
                $m.props.animReady = true;
                if ($m.props.animQueue !== null) {
                    $m.gotoSlide($m.props.animQueue, true, null);
                }
            };
            this.setNavActive = function (id) {
                $("li", $m.props.navContainer).removeClass("active");
                $("> li:eq(" + id + ")", $m.props.navContainer).addClass("active");
            };
            this.timerFunc = function () {
                $m.gotoSlide($m.props.currentSlide + 1, false, 1);
            };
            this.resetTimer = function (startNow) {
                clearInterval($m.props.timer);
                $m.props.timer = setInterval($m.timerFunc, $m.props.slideTime + $m.props.animTime);
                if (startNow) {
                    $m.timerFunc();
                }
            };
            this.resetAllSlidePositions = function () {
                for (var i = 0; i < $m.props.sCount; i++) {
                    $(".s-id-" + i, $m.props.sUL).remove().appendTo($m.props.sUL);
                }
            };
            this.setSlideOrder = function (focusOn) {
                var firstSlide = (focusOn - 1 < 0 ? $m.props.sCount - 1 : focusOn - 1);
                for (var i = 0; i < $m.props.sCount; i++) {
                    var thisSlide = firstSlide + i;
                    if (thisSlide >= $m.props.sCount) {
                        thisSlide -= $m.props.sCount;
                    }

                    $(".s-id-" + thisSlide, $m.props.sUL).remove().appendTo($m.props.sUL);
                }
            };
            this.buildBackNextLinks = function () {
                var backNextNav = '<ul class="slideshow-back-next">';
                backNextNav += '<li class="back-button"><a href="javascript:;">Back</a></li>';
                backNextNav += '<li class="next-button"><a href="javascript:;">Next</a></li>';
                backNextNav += '</ul>';
                $($m.props.sContainer).append(backNextNav);
            };
            this.buildPauseButton = function () {
                var pauseButton = '<p class="pause-button playing"><a href="javascript:;">Pause</a></p>';
                $($m.props.sContainer).append(pauseButton);
            };
            this.buildNav = function () {
                var $nav = $m.props.sUL.after('<ul class="' + $m.props.navContainerTitle + '" />');
                var $slides = $m.props.sUL.find("> li");
                var slideNavContent = "";
                for (var i = 0; i < $m.props.sCount; i++) {
                    var ref = $slides.attr("id");
                    slideNavContent += '<li></li>';
                }

                $("." + $m.props.navContainerTitle, $m.props.sContainer).append(slideNavContent);
            }

            this.init = function (root) {
                $m.props.sContainer = root;
                $($m.props.sliderHolder, $m.props.sContainer).wrap("<div class='slider-wrapper' />");
                $m.props.sWrapper = ($(".slider-wrapper", root));
                $("> ul", $m.props.sWrapper).addClass("s-active " + $m.props.animType);
                $m.props.timer = null;
                $m.props.prevSlide = null;
                $m.props.currentSlide = 0;
                $m.props.backNextContainer = ".slideshow-back-next";
                $m.props.pauseContainer = ".pause-button";
                $m.props.sRef = $($(".CarouSlide")).index($m.props.sContainer);
                $m.props.animReady = true;
                $m.props.animState = !$m.props.autoAnim ? "pause" : "play";
                $m.props.sUL = $(".s-active", $m.props.sWrapper);
                $m.props.sUL.find("> li", $m.props.sWrapper).each(function (id) {
                    $(this).addClass("slide").addClass("s-id-" + id);
                });
                $m.props.sCount = $(".s-active > li", $m.props.sWrapper).size();
                $m.props.sWidth = $(".s-active > li", $m.props.sWrapper).outerWidth();
                $m.props.sHeight = $(".s-active > li", $m.props.sWrapper).outerHeight();
                $m.props.navContainerTitle = $m.props.navContainer.split(".")[1];
                if ($m.props.hoverLinks == true) {
                    $m.props.animType = "none"
                }

                if ($m.props.showSlideNav && !$m.props.sContainer.find($m.props.navContainer).size()) {
                    $m.buildNav();
                }

                $m.props.navContainer = $m.props.sContainer.find($m.props.navContainer);
                if ($m.props.animType == "none") {
                    $m.props.animInfinity = false;
                    $m.props.alwaysNext = false;
                } else {
                    $m.props.hoverLinks = false;
                }

                if ($m.props.alwaysNext && $m.props.animType == "fade") {
                    $m.props.animType = "slide";
                }

                if ($m.props.animType == "fade" && ($m.props.animInfinity || $m.props.alwaysNext)) {
                    $m.props.animInfinity = false;
                    $m.props.alwaysNext = false;
                }

                if ($m.props.alwaysNext && $m.props.animInfinity) {
                    alert("DEVELOPER NOTICE:\n\nProperties 'alwaysNext' and 'aninInfinity' cannot both be active.\n'animInfinity' has been disabled.");
                    $m.props.animInfinity = false;
                }

                if ($m.props.animInfinity) {
                    $(".slide:last", $m.props.sUL).remove().prependTo($m.props.sUL);
                }

                if ($m.props.showSlideNav) {
                    $("> li:first", $m.props.navContainer).addClass("active");
                } else {
                    $($m.props.navContainer).hide();
                }

                if ($m.props.autoAnim && $m.props.showPauseButton) {
                    $m.buildPauseButton();
                }

                if ($m.props.showBackNext) {
                    $m.buildBackNextLinks();
                }

                switch ($m.props.animType) {
                case "fade":
                    $("> li", $m.props.sUL).css({
                        "opacity": "0",
                        "position": "absolute",
                        "left": 0,
                        "top": 0,
                        "z-index": 10
                    });
                    $("> li:first", $m.props.sUL).css({
                        "z-index": "100",
                        "opacity": "1"
                    });
                    break;
                case "none":
                    $(".s-active", $m.props.sWrapper).width(($m.props.sWidth * $m.props.sCount) + "px");
                    break;
                case "slide":
                    if ($m.props.animInfinity) {
                        $($m.props.sUL).css("left", -$m.props.sWidth + "px");
                    }

                    $(".s-active", $m.props.sWrapper).width(($m.props.sWidth * $m.props.sCount) + "px");
                    break;
                case "slide-vertical":
                    if ($m.props.animInfinity) {
                        $($m.props.sUL).css("top", -$m.props.sHeight + "px");
                    }

                    $("> ul", $m.props.sWrapper).height(($m.props.sHeight * $m.props.sCount) + "px");
                    break;
                default:
                }

                if ($m.props.autoAnim) {
                    $m.resetTimer();
                }
            };
        }

        return this.each(function (id, root) {
            var $m = new methods();
            $m.props = $.extend({}, $.fn.CarouSlide.config, userConfig);
            $m.init($(this));

            function slideLinkAction() {
                var pos = $(this).attr("rel");
                if ($m.props.animReady) {
                    $m.gotoSlide(pos, true, null);
                } else {
                    $m.props.animQueue = pos;
                }
            }

            if ($m.props.showSlideNav) {
                $("> li a", $m.props.navContainer).each(function (pos) {
                    var $events = $m.props.hoverLinks ? "mouseover click" : "click";
                    $(this).attr({
                        "href": "javascript:;",
                        "rel": pos
                    }).bind($events, slideLinkAction);
                });
            }

            var $allSlides = $("li.slide", $m.props.sContainer);
            for (var i = 0; i < $allSlides.length; i++) {
                var s = $(".s-id-" + i, $m.props.sContainer);
                var ref = s.attr("id");
                $("a[href=#" + ref + "]").attr({
                    "href": "javascript:;",
                    "rel": i
                }).bind("click", slideLinkAction);
            };
            if ($m.props.showBackNext) {
                $(".next-button", $m.props.sContainer).click(function () {
                    var nextPos = $m.props.currentSlide + 1 >= $m.props.sCount ? 0 : $m.props.currentSlide + 1;
                    if ($m.props.animReady) {
                        if ($m.props.animState == "play") {
                            $m.resetTimer();
                        }

                        $m.gotoSlide(nextPos, false, 1);
                    }
                });
                $(".back-button", $m.props.sContainer).click(function () {
                    var prevPos = $m.props.currentSlide - 1 < 0 ? $m.props.sCount - 1 : $m.props.currentSlide - 1;
                    if ($m.props.animReady) {
                        if ($m.props.animState == "play") {
                            $m.resetTimer();
                        }

                        $m.gotoSlide(prevPos, false, -1);
                    }
                });
            }

            if ($m.props.autoAnim && $m.props.showPauseButton) {
                $($m.props.pauseContainer, $m.props.sContainer).click(function () {
                    if ($m.props.animState == "pause") {
                        $m.props.animState = "play";
                        $m.resetTimer(true);
                        $(this).addClass("playing").find("a").text("pause");
                    }

                    else if ($m.props.animState == "play") {
                        $m.props.animState = "pause";
                        clearInterval($m.props.timer);
                        $(this).removeClass("playing").find("a").text("play");
                    }
                });
            }
        });
    };
})(jQuery);
