/**
 * jQuery Image Scroller
 * Copyright (c) 2011 Allan Ma (http://codecanyon.net/user/webtako)
 * Version: 1.3 (02/27/2011)
 */
;
(function($) {
    $.fn.wtScroller = function(params) {
        var TOP = "top";
        var BOTTOM = "bottom";
        var OUTSIDE = "outside";
        var INSIDE = "inside";
        var SLIDE_OPACITY = 1;
        var BUTTON_OPACITY = 0.7;
        var SCROLL_SPEED = 1000;
        var DEFAULT_DURATION = 600;
        var ANIMATE_SPEED = 300;
        var DEFAULT_DELAY = 4000;
        var UPDATE_BUTTONS = "update_buttons";
        var UPDATE_THUMB = "update_thumb";
        var UPDATE_INDEX = "update_index";
        var UPDATE_TEXT = "update_text";
        var START_TIMER = "start_timer";
        var LB_OPEN = "lightbox_open";
        var LB_CLOSE = "lightbox_close";

        //Class Scroller


        function Scroller($obj, opts) {
            var numDisplay = getPosNumber(opts.num_display, 3);
            var slideWidth = getPosNumber(opts.slide_width, 300);
            var slideHeight = getPosNumber(opts.slide_height, 200);
            var slideMargin = getNonNegNumber(opts.slide_margin, 1);
            var margin = getNonNegNumber(opts.margin, 10);
            var buttonWidth = getPosNumber(opts.button_width, 35);
            var ctrlHeight = getPosNumber(opts.ctrl_height, 20);
            var autoScroll = opts.auto_scroll;
            var delay = getPosNumber(opts.delay, DEFAULT_DELAY);
            var duration = getPosNumber(opts.scroll_speed, SCROLL_SPEED);
            var easing = opts.easing;
            var autoScale = opts.auto_scale;
            var displayButtons = opts.display_buttons;
            var ctrlType = opts.ctrl_type.toLowerCase();
            var displayCaption = opts.display_caption;
            var mouseoverCaption = opts.mouseover_caption;
            var captionPos = opts.caption_position.toLowerCase();
            var captionAlign = opts.caption_align.toLowerCase();
            var moveBy1 = opts.move_one;
            var contNav = opts.cont_nav;
            var shuffle = opts.shuffle;

            var $scroller;
            var $slidePanel;
            var $slideList;
            var $slides;
            var $prevBtn;
            var $nextBtn;
            var $cbar;
            var $indexes;
            var $scrollbar;
            var $thumb;
            var $items;

            var numItems;
            var unitSize;
            var prevSlots;
            var nextSlots;
            var maxSlots;
            var range;
            var pos;
            var timerId;
            var extOffset;
            var extHeight;
            var prevPct;

            this.init = function() {
                $scroller = $(".wt-scroller", $obj);
                $slidePanel = $scroller.find(".slides");
                $slideList = $slidePanel.find(">ul:first");
                $slides = $slideList.find(">li");
                $cbar = $scroller.find(".lower-panel");
                $prevBtn = $scroller.find(".prev-btn");
                $nextBtn = $scroller.find(".next-btn");
                extOffset = 0;
                extHeight = 0;
                pos = 0;
                prevPct = -1;
                timerId = null;
                numItems = $slides.size();
                if (numItems <= numDisplay) {
                    displayButtons = false;
                    ctrlType = "none";
                    numDisplay = numItems;
                }
                if (ctrlType == "index") {
                    moveBy1 = false;
                }

                //init components
                initItems();
                initSlidePanel();
                initCtrls();

                $scroller.css({
                    width: $slidePanel.width(),
                    height: $slidePanel.height() + $cbar.outerHeight(),
                    "padding-top": margin
                });

                if (shuffle) {
                    shuffleItems();
                }
                updateCPanel();
                $(document).bind(LB_CLOSE, onFocus).bind(LB_OPEN, onBlur);
                $scroller.trigger(LB_CLOSE);
            }

            //init slides
            var initItems = function() {
                initCaptions();
                $items = new Array(numItems);
                $slides.each(

                function(n) {
                    var $img = $(this).find("img:first");
                    var $link = $(this).find(">a:first");
                    if (!$link.attr("href")) {
                        $(this).click(preventDefault);
                        $link.css("cursor", "default");
                    } else {
                        $link.data("text", $(this).find(">p:first").html());
                    }
                    if (autoScale) {
                        $img[0].complete || $img[0].readyState == "complete" ? processImg($img) : $img.load(processLoadedImg);
                    }
                    if (displayCaption && captionPos == INSIDE) {
                        initCaption($(this));
                    }
                    $items[n] = $(this);
                });
            }

            //init captions
            var initCaptions = function() {
                var $captions = $slides.find(">p:first");
                if (displayCaption) {
                    var padding = $captions.outerWidth() - $captions.width();
                    $captions.css({
                        width: slideWidth - padding,
                        visibility: "visible"
                    }).click(preventDefault);
                    if (captionPos == OUTSIDE) {
                        var heights = $captions.map(function() {
                            return $(this).height();
                        }).get();
                        var maxHeight = Math.max.apply(Math, heights);
                        $captions.css({
                            top: captionAlign == TOP ? 0 : slideHeight,
                            height: maxHeight
                        });

                        extHeight = $captions.outerHeight();
                        if (captionAlign == TOP) {
                            extOffset = extHeight;
                        }
                        $captions.addClass("outside");
                    } else {
                        $captions.addClass("inside");
                    }
                } else {
                    $captions.hide();
                }
            }

            //init caption
            var initCaption = function($item) {
                var $caption = $item.find(">p:first");
                if ($caption.length < 1 || $caption.html() == "") {
                    $caption.remove();
                    return;
                }
                if (mouseoverCaption) {
                    $caption.css("top", captionAlign == TOP ? -$caption.outerHeight() : slideHeight);
                    $item.hover(showCaption, hideCaption);
                } else {
                    $caption.css("top", captionAlign == TOP ? 0 : slideHeight - $caption.outerHeight());
                }
            }

            //init slide panel
            var initSlidePanel = function() {
                $slides.css({
                    width: slideWidth,
                    height: slideHeight + extHeight,
                    "margin-right": slideMargin
                }).hover(itemMouseover, itemMouseout);
                $slidePanel.css({
                    width: (numDisplay * $slides.width()) + ((numDisplay - 1) * slideMargin),
                    height: $slides.height()
                });
                unitSize = $slides.outerWidth(true);
                var num;
                if (ctrlType == "index") {
                    num = numDisplay * Math.ceil(numItems / numDisplay);
                } else {
                    num = numItems;
                }
                $slideList.width(num * unitSize);
                maxSlots = num - numDisplay;
                prevSlots = 0;
                nextSlots = maxSlots;

                range = (($slideList.width() - slideMargin) - $slidePanel.width());
            }

            var initCtrls = function() {
                initButtons();
                $cbar.css({
                    width: $slidePanel.width(),
                    "padding-left": 0,
                    "padding-right": 0
                });
                switch (ctrlType) {
                case "scrollbar":
                    initScrollbar();
                    var ctrlMargin = Math.max((ctrlHeight - $scrollbar.height()) / 2, 0);
                    $cbar.css({
                        "padding-top": ctrlMargin,
                        "padding-bottom": ctrlMargin
                    });
                    break;
                case "index":
                    initIndexes();
                    var ctrlMargin = Math.max((ctrlHeight - $indexes.height()) / 2, 0);
                    $cbar.css({
                        "padding-top": ctrlMargin,
                        "padding-bottom": ctrlMargin
                    });
                    break;
                default:
                    $cbar.remove();
                    $scroller.css("padding-bottom", margin);
                }
            }

            //init buttons
            var initButtons = function() {
                if (displayButtons) {
                    $prevBtn.css({
                        width: buttonWidth,
                        height: 9
                    }).mousedown(preventDefault).click(moveBack);
                    $nextBtn.css({
                        width: buttonWidth,
                        height: 9
                    }).mousedown(preventDefault).click(moveFwd);
                    if (!contNav) {
                        $scroller.bind(UPDATE_BUTTONS, updateButtons);
                    }
                } else {
                    $prevBtn.remove();
                    $nextBtn.remove();
                    $scroller.css({
                        "padding-left": margin,
                        "padding-right": margin
                    });
                }
            }

            //update buttons
            var updateButtons = function() {
                var begIndex = Math.abs(pos / unitSize);
                var endIndex = begIndex + numDisplay;
                $prevBtn.css(begIndex > 0 ? {
                    opacity: 1,
                    cursor: "pointer"
                } : {
                    opacity: BUTTON_OPACITY,
                    cursor: "default"
                });
                $nextBtn.css(endIndex < numItems ? {
                    opacity: 1,
                    cursor: "pointer"
                } : {
                    opacity: BUTTON_OPACITY,
                    cursor: "default"
                });
            }

            //init scrollbar
            var initScrollbar = function() {
                $cbar.append("<div class='scroll-bar'><div class='thumb'></div></div>");
                $scrollbar = $cbar.find("div.scroll-bar");
                $thumb = $cbar.find("div.thumb");
                $scrollbar.width($cbar.width()).click(trackClick).mousedown(preventDefault);
                $thumb.width(Math.ceil((numDisplay / numItems) * $scrollbar.width())).click(preventDefault);

                var scrollRange = $scrollbar.width() - $thumb.width();
                var moveRatio = range / scrollRange;
                try {
                    $thumb.draggable({
                        containment: "parent"
                    }).bind("drag", function() {
                        $slideList.css({
                            left: Math.round(-$thumb.position().left * moveRatio)
                        });
                    }).bind("dragstop", function() {
                        autoStop($thumb.position().left / scrollRange);
                    });
                } catch (ex) { //not draggable. 
                }

                $scroller.bind(UPDATE_THUMB, function() {
                    var move = Math.round(Math.abs(pos) * (1 / moveRatio));
                    $thumb.stop(true, true).animate({
                        left: move
                    }, duration, easing);
                });
            }

            //init indexes
            var initIndexes = function() {
                var n = Math.ceil(numItems / numDisplay);
                var str = "";
                for (var i = 0; i < n; i++) {
                    str += "<span class='index'></span>";
                }
                $cbar.prepend(str);
                $indexes = $cbar.find(".index").mousedown(preventDefault).bind("click", goToIndex);
                $scroller.bind(UPDATE_INDEX, updateIndexes);
            }

            //update indexes
            var updateIndexes = function() {
                var i = Math.ceil(prevSlots / numDisplay);
                $indexes.filter(".index-hl").removeClass("index-hl");
                $($indexes.get(i)).addClass("index-hl");
            }

            //update slide list
            var updateSlideList = function() {
                pos = -prevSlots * unitSize;
                $slideList.stop(true, true).animate({
                    left: pos
                }, duration, easing, function() {
                    $scroller.trigger(START_TIMER);
                });
                updateCPanel();
            }

            //update controls
            var updateCPanel = function() {
                $scroller.trigger(UPDATE_BUTTONS).trigger(UPDATE_THUMB).trigger(UPDATE_INDEX);
            }

            //track click
            var trackClick = function(e) {
                autoStop((e.pageX - $scrollbar.offset().left) / $scrollbar.width());
            }

            //auto stop
            var autoStop = function(pct) {
                if (pct != prevPct) {
                    prevPct = pct;
                    var move;
                    var newPos = pct * range;
                    if (newPos > Math.abs(pos)) {
                        move = Math.ceil(newPos / unitSize);
                    } else if (newPos < Math.abs(pos)) {
                        move = Math.floor(newPos / unitSize);
                    } else {
                        return;
                    }
                    var slots = move + (pos / unitSize);
                    prevSlots += slots;
                    nextSlots -= slots;
                    updateSlideList();
                }
            }

            //go to index			
            var goToIndex = function() {
                stopTimer();
                prevSlots = $(this).index() * numDisplay;
                nextSlots = maxSlots - prevSlots;
                updateSlideList();
                return false;
            }

            //move slides back
            var moveBack = function() {
                stopTimer();
                if (nextSlots < maxSlots) {
                    var slots = moveBy1 ? 1 : Math.min(maxSlots - nextSlots, numDisplay);
                    nextSlots += slots;
                    prevSlots -= slots;
                } else if (contNav) {
                    nextSlots = 0;
                    prevSlots = maxSlots;
                } else {
                    return;
                }
                updateSlideList();
            }

            //move slides forward
            var moveFwd = function() {
                stopTimer();
                if (prevSlots < maxSlots) {
                    var slots = moveBy1 ? 1 : Math.min(maxSlots - prevSlots, numDisplay);
                    prevSlots += slots;
                    nextSlots -= slots;
                } else if (contNav) {
                    prevSlots = 0;
                    nextSlots = maxSlots;
                } else {
                    return;
                }
                updateSlideList();
            }

            //rotate slides forward
            var rotateFwd = function() {
                stopTimer();
                if (prevSlots < maxSlots) {
                    var slots = moveBy1 ? 1 : Math.min(maxSlots - prevSlots, numDisplay);
                    prevSlots += slots;
                    nextSlots -= slots;
                } else {
                    prevSlots = 0;
                    nextSlots = maxSlots;
                }
                updateSlideList();
            }

            //process loaded image size & position
            var processLoadedImg = function() {
                processImg($(this));
            }

            //process image
            var processImg = function($img) {
                if ($img.outerWidth() > 0 && $img.outerHeight() > 0) {
                    var sizeRatio;
                    if ($img.outerWidth() > slideWidth) {
                        sizeRatio = $img.outerHeight() / $img.outerWidth();
                        $img.css({
                            width: slideWidth,
                            height: sizeRatio * slideWidth
                        });
                    }
                    if ($img.outerHeight() > slideHeight) {
                        sizeRatio = $img.outerWidth() / $img.outerHeight();
                        $img.css({
                            width: sizeRatio * slideHeight,
                            height: slideHeight
                        });
                    }
                    $img.css({
                        left: Math.round((slideWidth - $img.outerWidth()) / 2),
                        top: extOffset + Math.round((slideHeight - $img.outerHeight()) / 2)
                    });
                }
            }

            //scroller blur
            var onBlur = function() {
                $scroller.unbind(START_TIMER).unbind("mouseenter").unbind("mouseleave");
                stopTimer();
                $(document).unbind("keyup", onScrollKeyPress);
            }

            //scroller focus
            var onFocus = function() {
                if (autoScroll) {
                    $scroller.bind(START_TIMER, startTimer).hover(scrollerOver, scrollerOut).trigger(START_TIMER);
                }
                $(document).bind("keyup", onScrollKeyPress);
            }

            //item mouseover
            var itemMouseover = function() {
                $(this).find("img:first").stop().animate({
                    opacity: SLIDE_OPACITY
                }, ANIMATE_SPEED);
            }

            //item mouseout
            var itemMouseout = function() {
                $(this).find("img:first").stop().animate({
                    opacity: 1
                }, ANIMATE_SPEED, function() {
                    if (jQuery.browser.msie) {
                        this.style.removeAttribute('filter');
                    }
                });
            }

            //show caption
            var showCaption = function() {
                var $caption = $(this).find(">p:first");
                $caption.stop().animate({
                    top: captionAlign == BOTTOM ? slideHeight - $caption.outerHeight() : 0
                }, ANIMATE_SPEED);
            }

            //hide caption
            var hideCaption = function() {
                var $caption = $(this).find(">p:first");
                $caption.stop().animate({
                    top: captionAlign == BOTTOM ? slideHeight : -$caption.outerHeight()
                }, ANIMATE_SPEED);
            }

            //scroller over
            var scrollerOver = function() {
                $scroller.unbind(START_TIMER);
                stopTimer();
            }

            //scroller out
            var scrollerOut = function() {
                $scroller.bind(START_TIMER, startTimer).trigger(START_TIMER);
            }

            //key press
            var onScrollKeyPress = function(e) {
                switch (e.keyCode) {
                case 37:
                    moveBack();
                    break;
                case 39:
                    moveFwd();
                    break;
                }
            }

            //prevent default behavior
            var preventDefault = function() {
                return false;
            }

            //shuffle items
            var shuffleItems = function() {
                for (var i = 0; i < $items.length; i++) {
                    var ri = Math.floor(Math.random() * $items.length);
                    var temp = $items[i];
                    $items[i] = $items[ri];
                    $items[ri] = temp;
                }

                for (var i = 0; i < $items.length; i++) {
                    $items[i] = $items[i].clone(true);
                }

                for (var i = 0; i < $items.length; i++) {
                    $($slides.get(i)).replaceWith($items[i]);
                }
            }

            //start timer
            var startTimer = function() {
                if (timerId == null) {
                    timerId = setTimeout(rotateFwd, delay);
                }
            }

            //stop timer
            var stopTimer = function() {
                clearTimeout(timerId);
                timerId = null;
            }
        }

        //get positive number
        var getPosNumber = function(val, defaultVal) {
            if (!isNaN(val) && val > 0) {
                return val;
            }
            return defaultVal;
        }

        //get nonnegative number
        var getNonNegNumber = function(val, defaultVal) {
            if (!isNaN(val) && val >= 0) {
                return val;
            }
            return defaultVal;
        }

        var defaults = {
            num_display: 3,
            slide_width: 300,
            slide_height: 200,
            slide_margin: 1,
            button_width: 35,
            ctrl_height: 20,
            margin: 10,
            auto_scroll: true,
            delay: DEFAULT_DELAY,
            scroll_speed: SCROLL_SPEED,
            easing: "",
            auto_scale: true,
            move_one: false,
            ctrl_type: "scrollbar",
            display_buttons: true,
            display_caption: true,
            mouseover_caption: false,
            caption_align: BOTTOM,
            caption_position: INSIDE,
            cont_nav: true,
            shuffle: false
        };

        var opts = $.extend(true, {}, defaults, params);
        return this.each(

        function() {
            var scroller = new Scroller($(this), opts);
            scroller.init();
        });
    }
})(jQuery);
