"use strict";

jQuery.fn.scroller = function (opts) {

    var TRANSITION_FADE = 'fade',
        TRANSITION_SCROLL = 'scroll',
        animateSpeed = opts.animateSpeed || 1000,
        perPage = opts.perPage || 4,
        maxHeight = opts.maxHeight || null,
        itemClass = opts.itemClass || 'item',
        firstButton = opts.firstButton || null,
        leftButton = opts.leftButton || '&#171;',
        rightButton = opts.rightButton || '&#187;',
        lastButton = opts.lastButton || null,
        counter = opts.counter || null,
        dotCounter = opts.dotCounter || false,
        autoSize = opts.autoSize || false,
        secondPager = opts.secondPager || false,
        auto = opts.auto || false,
        autoSpeed = opts.autoSpeed || 4000,
        mouseOutDelay = opts.mouseOutDelay || 8000,
        transition = opts.transition || TRANSITION_SCROLL,
        obj = this,
        pagerHtml = '',
        pageWidth = 0,
        currentPage = 0,
        cancelAuto = false,
        canvasHeight = null,
        h = null,
        timeoutId = null,
        playOn = null;

    //Group the contents into per-page groups.
    this.canvas = $('<div class="canvas"></div>');

    canvasHeight = $(this.canvas).height();

    this.pagify = function () {

        if (maxHeight) {
            var pageHeight = 0;
            $('.' + itemClass, obj).each(function (i) {
                if (i === 0 || (pageHeight + $(this).outerHeight()) > maxHeight) {
                    obj.canvas.append($('<div class="page"></div>'));
                    pageHeight = 0;
                }
                if ($(this).css('display') !== 'none') {
                    pageHeight = pageHeight + $(this).outerHeight();
                }
                $(this).detach();
                $('div.page:last', obj.canvas).append($(this));
            });
        }
        else {
            $('.' + itemClass, obj).each(function (i) {
                if (i === 0 || i % perPage === 0) {
                    obj.canvas.append($('<div class="page"></div>'));
                }
                $(this).detach();
                $('div.page:last', obj.canvas).append($(this));
            });
        }
        this.setPagination();

    };

    this.setPagination = function () {
        var i = 0,
            el = null,
            alt = null;

        if (counter) {
            counter = counter.replace(/\?/, '<span class="pos">1</span>');
            counter = counter.replace(/#/, '<span class="total">' + $('div.page', obj.canvas).length + '</span>');
            $('.counter', obj).html(counter);
        }

        if (dotCounter) {
            $('.dot-counter', obj).html('<ol></ol>');
            for (i = 0; i < $('div.page', obj.canvas).length; i = i + 1) {
                el = $('div.page', obj.canvas)[i];
                alt = $(el).find("img").attr("alt");
                alt = alt ? alt.replace('"', "'") : "";
                $('div.page').attr("title", alt);
                $('.dot-counter ol', obj).append($('<li title="' + alt + '" class="page-dot' + ((i === 0) ? ' first' : '') + ((i === $('div.page', obj.canvas).length) ? ' last' : '') + '"><a href="#" title="' + alt + '" slide="' + i + '"><span>' + (i + 1) + '</span></a></li>'));
            }

            $('.page-dot a').click(function () {
                obj.moveToPage(parseInt($(this).attr('slide'), 10));
                return false;
            });

            $('.page-dot:first', obj).addClass('selected');
        }
    };

    this.pagify();

    $(this).append(obj.canvas);

    $(this).wrapInner('<div class="frame"></div>');

    $(this).addClass('scroller');

    pageWidth = $('.page', obj).outerWidth();

    if (transition === TRANSITION_FADE) {
        $('.page', obj).each(function (i) {
            $(this).css({ left: '0', position: 'absolute', display: i === 0 ? 'block' : 'none' });
        });
    }
    else {
        $('.page', obj).each(function (i) {
            $(this).css({ left: (i * pageWidth) + 'px', position: 'absolute' });
        });
    }

    obj.pages = $('.page', obj).get();

    if (obj.pages.length > 1) {
        pagerHtml = '<div class="scroller_pagination"><a class="left-button" href="#">' + leftButton + '</a><span class="counter"></span><span class="dot-counter"></span><a class="right-button" href="#">' + rightButton + '</a></div>';
        $(this).append($(pagerHtml));
        if (secondPager) {
            pagerHtml = '<div class="scroller_pagination second-pager"><a class="left-button" href="#">' + leftButton + '</a><span class="counter"></span><span class="dot-counter"></span><a class="right-button" href="#">' + rightButton + '</a></div>';
            $(this).prepend($(pagerHtml));
        }
    }
    else {
        if (autoSize) {
            h = $('.page', obj).height();
            $('.frame', obj).css('height', h + 'px');
        }
    }

    if (firstButton && counter) {
        $('.scroller_pagination', this).prepend('<a class="first-button" href="#">' + firstButton + '</a>');
    }
    if (lastButton && counter) {
        $('.scroller_pagination', this).append('<a class="last-button" href="#">' + lastButton + '</a>');
    }
    this.setPagination();

    obj.movePage = function (direction) {
        var canvas = $('.canvas', obj),
            counterObjs = $('.pos', obj),
            pg = 0,
            pages = $('div.page', obj).length,
            curLeft = canvas.position().left,
            dots = $('.page-dot', obj);

        if (obj.inMotion) {
            return false;
        }

        obj.inMotion = true;
        obj.dist = direction;

        pg = currentPage;

        if (direction > 0) {
            obj.pageRight();

            if (transition === TRANSITION_FADE) {
                $('.page:visible', obj).fadeOut(opts.animateSpeed);
                $(obj.pages[0]).fadeIn(opts.animateSpeed);
                obj.motionComplete();
            }
            else {
                canvas.animate({ left: (curLeft + (pageWidth * direction)) + 'px' }, { duration: animateSpeed, complete: obj.motionComplete });
            }
            //pg = pg - 1;
        }
        else {
            //obj.pageLeft();
            if (transition === TRANSITION_FADE) {
                $('.page:visible', obj).fadeOut(opts.animateSpeed);
                $(obj.pages[direction * -1]).fadeIn(opts.animateSpeed);
                obj.pageLeft();
            }
            else {
                canvas.animate({ left: (curLeft + (pageWidth * direction)) + 'px' }, { duration: animateSpeed, complete: obj.pageLeft });
            }
            //pg = pg + 1

        }
        pg = pg + (direction * -1);
        if (pg < 0) {
            pg = pages - 1;
        }
        if (pg > (pages - 1)) {
            pg = 0;
        }

        if (counterObjs) {
            $('.pos', obj).text(pg + 1);
        }
        if (dotCounter) {
            dots.removeClass('selected');
            $(dots[pg]).addClass('selected');
        }
        currentPage = pg;
        clearTimeout(timeoutId);
        timeoutId = setTimeout(obj.autoMove, autoSpeed);
        return false;
    };

    $(this).bind('repage', function (e) {
        $('.' + itemClass, obj).unwrap();
        obj.pagify();
        $('.page', obj).each(function (i) {
            $(this).css({ left: (i * pageWidth) + 'px', position: 'absolute' });
        });

        obj.pages = $('.page', obj).get();

        if (obj.pages.length > 1) {
            $('.scroller_pagination', obj).show();
        }
        else {
            $('.scroller_pagination', obj).hide();
        }
        $('.canvas', obj).css({ left: '0px' });
    });

    obj.motionComplete = function () {
        obj.inMotion = false;
    };

    obj.pageLeft = function () {
        var page = null,
            rightMost = null,
            i = 0;
        //take leftmost page, move it to the right end.
        for (i = 1; i <= Math.abs(obj.dist); i = i + 1) {
            //console.log('pageLeft: ' + i + '/' + Math.abs(obj.dist));
            page = obj.pages.shift();

            if (transition === TRANSITION_SCROLL) {
                rightMost = $(obj.pages[obj.pages.length - 1]).position();
                $(page).css({ left: (rightMost.left + pageWidth) });
            }
            obj.pages.push(page);
        }
        obj.motionComplete();
    };

    obj.pageRight = function () {
        var page = null,
            leftMost = null,
            i = 0;
        //take rightmost page, move it to the left end.
        for (i = 1; i <= Math.abs(obj.dist); i = i + 1) {
            //console.log('pageRight: ' + i + '/' + Math.abs(obj.dist));
            page = this.pages.pop();

            if (transition === TRANSITION_SCROLL) {
                leftMost = $(this.pages[0]).position();
                $(page).css({ left: (leftMost.left - pageWidth) });
            }

            this.pages.unshift(page);
        }
    };

    obj.moveToPage = function (targetPage) {
        var pos = currentPage,
            dist = targetPage - pos;

        obj.movePage(dist * -1);
        return false;
    };

    obj.inMotion = false;

    obj.autoMove = function () {
        if (!cancelAuto) {
            obj.movePage(-1);
        }
    };

    $('.right-button', this).click(function () {
        obj.movePage(-1);
        return false;
    });

    $('.left-button', this).click(function () {
        obj.movePage(1);
        return false;
    });

    $('.last-button', this).click(function () {
        var pos = parseInt($('.pos:first', obj).text(), 10),
            pages = $('div.page', obj).length,
            dist = pages - pos;

        obj.movePage(dist * -1);
        return false;
    });

    $('.first-button', this).click(function () {
        var pos = parseInt($('.pos:first', obj).text(), 10),
            dist = pos - 1;

        obj.movePage(dist);
        return false;
    });

    if (auto) {
        obj.mouseover(function () {
            cancelAuto = true;
            clearTimeout(playOn);
        });

        obj.mouseleave(function () {
            cancelAuto = false;
            playOn = setTimeout(obj.autoMove, mouseOutDelay);
        });

        setTimeout(obj.autoMove, autoSpeed);
    }

};

