﻿"SMART.Pagination".namespace();

SMART.Pagination = function() {

    // PRIVATE MEMBERS
    var CONST_NOT_APPLICABLE = ".not-applicable";
    var itemsContainer;
    var items; // 
    var paginationControlContainer;
    var prevButton;
    var nextButton;
    var resultCountLabel;
    var currentPageLabel;
    var maxPageLabel;
    var selectedItemsPerPageLabel;
    var resultsPerPage;

    var currentPage = 1;
    var pageLength;

    var resultsPerPageValueSelector;
    var itemHolderLastClassSelector;
    var groupClassSelector;

    // NAVIGATION
    var nextPage = function() {
        if (currentPage >= calculateMaxPageNumber())
            return;

        showPage(currentPage + 1);

        return false;
    };

    var previousPage = function() {
        if (currentPage <= 1)
            return;

        showPage(currentPage - 1);

        return false;
    };

    var gotoPage = function(pageNumber) {
        if (pageNumber > 0 && pageNumber <= calculateMaxPageNumber())
            showPage(pageNumber);

        return false;
    };


    // VISUALS

    var hideAllItems = function() {
        items.hide();
    }

    var showPage = function(pageNumber) {

        if (getTotalCount() == 0)
            return;

        // remove a class
        if (itemHolderLastClassSelector != CONST_NOT_APPLICABLE)
        {
            var lastClassWithoutDot = itemHolderLastClassSelector.replace(".", "");
            items.removeClass(lastClassWithoutDot);
        }
        
        if (pageNumber > calculateMaxPageNumber())
            throw ("pageNumber out of range");

        var resultset = getItemsForDisplay(pageNumber);
        var hideset = getItemsToHide(pageNumber);

        // remove the underline
        if (itemHolderLastClassSelector != CONST_NOT_APPLICABLE)
            resultset.last().addClass(lastClassWithoutDot);

        // quickly hide items so we can fade them in
        resultset.hide().fadeIn();
        hideset.hide();

        setStateOfPreviousNext();
        calculatePageBookmark();
        
        itemsContainer.find(groupClassSelector).each(function() {
            var r = $j(this).find(itemHolderClassSelector + ":not(:hidden)");
            if(r.length > 0) {
                $j(this).show();
            }
            else {
                $j(this).hide();
            };
        });
        
    }

    var setStateOfPreviousNext = function() {

        // logic to determine what the state is

        // if first page, previous = disabled
        if (currentPage == 1)
            enablePrevious(false);
        else
            enablePrevious(true);

        // if last page, next = disabled
        if (currentPage == calculateMaxPageNumber())
            enableNext(false);
        else
            enableNext(true);

    }

    var enableNext = function(state) {
        if (state === true) {
            nextButton.removeClass("RightDisabled").addClass("RightArrow");
        }
        else {
            nextButton.removeClass("RightArrow").addClass("RightDisabled");
        }
    }

    var enablePrevious = function(state) {
        if (state === true) {
            prevButton.removeClass("LeftDisabled").addClass("LeftArrow");
        }
        else {
            prevButton.removeClass("LeftArrow").addClass("LeftDisabled");
        }
    }




    // SIZING / COUNT METHODS

    var getItemsForDisplay = function(pageNumber) {
        currentPage = pageNumber;

        if (pageNumber == 1)
            return itemsContainer.find(itemHolderClassSelector + ":lt(" + (currentPage * pageLength) + ")");

        return itemsContainer.find(itemHolderClassSelector + ":lt(" + (currentPage * pageLength) + "):gt(" + (((currentPage - 1) * pageLength) - 1) + ")");
    }

    var getItemsToHide = function(pageNumber) {

        currentPage = pageNumber;

        if (pageNumber == 1)
            return itemsContainer.find(itemHolderClassSelector + ":gt(" + ((currentPage * pageLength) - 1) + ")");

        var itemsBefore = itemsContainer.find(itemHolderClassSelector + ":lt(" + ((currentPage - 1) * pageLength) + ")");
        var itemsAfter = itemsContainer.find(itemHolderClassSelector + ":gt(" + ((currentPage * pageLength) - 1) + ")");

        return itemsBefore.add(itemsAfter);
    }


    var getTotalCount = function() {
        return items.length;
    }

    var updateTotalCount = function() {

        var totalCount = getTotalCount();

        // safety checks
        if (totalCount === undefined)
            totalCount = 0;

        resultCountLabel.text(totalCount);

    }

    var setItemsPerPage = function(itemsPerPage) {
        if (itemsPerPage.constructor !== Number)
            itemsPerPage = 10;

        pageLength = itemsPerPage;
        calculatePageBookmark();
    }

    var calculatePageBookmark = function() {

        var numberOfPages = calculateMaxPageNumber;

        currentPageLabel.text(currentPage);
        maxPageLabel.text(numberOfPages);
        selectedItemsPerPageLabel.text(pageLength);
    }

    var calculateMaxPageNumber = function() {
        return Math.ceil(getTotalCount() / pageLength);
    }

    // VALIDATION

    var validate = function(attributes) {
        if (attributes.constructor !== Object)
            throw ("attributes is not a JSON object")

        if (attributes.itemContainerSelector === undefined)
            throw ("itemContainerSelector not set");

        if (attributes.itemSelector === undefined)
            throw ("itemSelector not set");

    };

    var bindEvents = function(attributes) {
        nextButton.click(function(e) {
            nextPage();
            SMART.Killswitch.Nuke();
            return false;
        });

        prevButton.click(function(e) { previousPage(); SMART.Killswitch.Nuke(); return false; });

        resultsPerPage.each(function() {

            $j(this).click(
                function(e) {
                    var shoudlBeANumber = getListItemValue(this, resultsPerPageValueSelector);
                    setItemsPerPage(shoudlBeANumber);
                    showPage(1);
                }
            );

        });

        return false;
    };

    var getListItemValue = function(listItem, valueSelector) {
        if (listItem === undefined || valueSelector === undefined)
            return getTotalCount();

        var value = $j(listItem).find(valueSelector).text();



        var number = parseInt(value);

        if (isNaN(number))
            return getTotalCount();

        return number;
    }

    // PUBLIC METHODS
    pub = {

        Init: function(attributes) {

            validate(attributes);

            paginationControl = $j(attributes.paginationControlSelector || ".pagination");
            prevButton = $j(attributes.prevButtonSelector || ".previous-button");
            nextButton = $j(attributes.nextButtonSelector || ".next-button");
            resultCountLabel = $j(attributes.resultCountSelector || ".results-count");
            currentPageLabel = $j(attributes.currentPageSelector || ".current-page");
            resultsPerPage = $j(attributes.resultsPerPageSelector || ".items-per-page");
            resultsPerPageValueSelector = attributes.resultsPerPageValueSelector || ".items-per-page-value";
            selectedItemsPerPageLabel = $j(attributes.selectedItemsPerPageSelector || ".selected-items-per-page");
            maxPageLabel = $j(attributes.maxPageSelector || ".max-page");
            
            itemsContainer = $j(attributes.itemContainerSelector);
            items = itemsContainer.find(attributes.itemSelector);

            itemHolderClassSelector = attributes.itemSelector;
            itemHolderLastClassSelector = attributes.itemHolderLastClassSelector || CONST_NOT_APPLICABLE;
            groupClassSelector = attributes.groupClassSelector || CONST_NOT_APPLICABLE;
            updateTotalCount();
            setItemsPerPage(attributes.itemsPerPage || 10);

            bindEvents();

            if (getTotalCount() === 0)
                paginationControl.hide();

            showPage(1);

        },

        SetItemsPerPage: function(itemsPerPage) {
            setItemsPerPage(itemsPerPage);
        },

        NextPage: function() {
            return nextPage();
        },

        PreviousPage: function() {
            return previousPage();
        },

        GotoPage: function(pageNumber) {
            return gotoPage(pageNumber);
            
        }
    };

    return pub;

} ();

