/**
 * This function assumes an array index for the current item.  The range
 * allowed can be 0 to array.length - 1.
 *
 * There are two ways to calculate the pagination. The first is to assume that
 * the itemId selected can fall anywhere in the page.  This makes the pagination
 * simple since we'll start at 0, add on pageSizes and this will determine what
 * page we're on and what the ranges are for each page.
 *
 * The other more complicated way to paginate (as used in the ecards browse
 * page) is to always make the currentIndex the very first item on the page
 * and make the first half of the pagination deal with the possiblility that
 * when the user browses to the beginning of the list, that there may be some
 * overlap with page 1 and page two.  This allows the page to dynamically add
 * or subtract items from the page without ever bumping the first item off
 * of the page.
 *
 * This function will create an array with the following information:
 *
 *      totalNumPages:  The total number of pages
 *      currentPageNum: What page the currentIndex fall on (starting from page 1)
 *      pageInfoArr:  An array indexed by page number containing the start & end
 *              indices for the page.
 *      displayListArr:  An array of the pages to be displayed based on the numXXXPages
 *              values.  For any slot that should be elipsis, the value will be -1.
 *              Otherwise, the value will be the page number to be displayed.
 *
 * @param int currentIndex -- The current item index (starting at 1)
 * @param int pageSize -- The number of items per page
 * @param totalNumItems -- How many items we have in total
 * @param indexAlwaysFirst -- Whether or not we assume the index is the first item
 * @param numPrePages -- Number of pages to display prior to the currently selected page
 * @param numPostPages -- Number of pages to display after the currently selected page
 * @param numStartPages -- Number of pages to display starting from page 1
 * @param numEndPages -- Number of pages to display counting back from the total
 *      number of pages.
 * @return array
 *
 */

function calculatePagination(
    currentIndex,
    pageSize,
    totalNumItems,
    indexAlwaysFirst,
    numPrePages,
    numPostPages,
    numStartPages,
    numEndPages
) {

    var paginationArr = new Array();

    if ( (currentIndex == undefined) || (pageSize == undefined) || (totalNumItems == undefined) ) {
        return paginationArr;
    }

    if ( (currentIndex < 1) || (pageSize < 1) || (totalNumItems < 1) ) {
        return paginationArr;
    }

    if (indexAlwaysFirst == undefined) {
        indexAlwaysFirst = false;
    } else {
        indexAlwaysFirst = (indexAlwaysFirst == true);
    }

    if (numPrePages == undefined) {
        numPrePages = 3;
    }

    if (numPostPages == undefined) {
        numPostPages = 3;
    }

    if (numStartPages == undefined) {
        numStartPages = 2;
    }

    if (numEndPages == undefined) {
        numEndPages = 2;
    }


    // First we must go through and calculate our pageInfoArr array with all
    // the start and end indices for each page.  This will differ based on
    // our choice of whether or not the currentIndex is always first on the
    // current page.

    var currentPageNum = Math.floor(currentIndex / pageSize);
    if ((currentIndex % pageSize) != 0) {
        // ie:  if 5 items per page and we're index #5, we should be on
        // page 1 rather than page 2.  Only add when it's not the last
        // item of that page.
        currentPageNum++;
    }
    if (indexAlwaysFirst && ( (currentIndex % pageSize) != 1)) {
        // This means we'll be adding an extra page in the front.  The actual
        // currentPageNum needs to be bumped up by one.
        currentPageNum++;
    }


    var pageInfoArr = new Array();
    var start;
    var end;

    var pageNum = 1;
    if (indexAlwaysFirst) {
        start = currentIndex % pageSize;
        if ((currentIndex % pageSize) != 1) {
            pageInfoArr[1] = {start: 1, end: Math.min(totalNumItems, pageSize)};
            pageNum++;
        }
    } else {
        start = 1;
    }

    var totalNumPages;
    for (; start <= totalNumItems; start+= pageSize) {
        totalNumPages = pageNum;
        end = start + pageSize - 1;
        if (end > totalNumItems) {
            end = totalNumItems;
        }
        pageInfoArr[pageNum] = {start: start, end: end};
        pageNum++;
    }

    // Now we have our entire array of pageInfoArr.  We need to now create the array
    // of page numbers and -1 to indicate that we need to put dots in that place.

    var displayListArr = new Array();
    var low_start = 1;
    var high_start = Math.min(numStartPages, totalNumPages);
    for (var i = low_start; i <= high_start; i++) {
        displayListArr[displayListArr.length] = i;
    }

    // Now simple math (numStartPages + 1) == (currentPageNum - numPrePages - 1)
    // Means that we have a case of 1 2 ... 4 5 .   So instead of putting dots
    // for 3, we'll just fill it in.

    if ((numStartPages + 1) == (currentPageNum - numPrePages - 1)) {
        displayListArr[displayListArr.length] = numStartPages + 1;
    } else if ((numStartPages + 1) < (currentPageNum - numPrePages - 1)) {
        // Put in dots if there'll be a gap.
        displayListArr[displayListArr.length] = -1;
    }

    var low_middle = Math.max(
        (high_start + 1), // No overlap
        (currentPageNum - numPrePages)
    );
    var high_middle = Math.min(
        (currentPageNum + numPostPages),
        (totalNumPages)
    );

    for (var i = low_middle; i <= high_middle; i++ ) {
        displayListArr[displayListArr.length] = i;
    }

    // Now simple math (currentPageNum + numPostPages + 1) == (totalNumPages - numEndPages)
    // Means that we have a case of 4 5 6 ... 8 9   So instead of putting dots
    // for 7, we'll just fill it in.  It is correct that we don't have the extra
    // -1 from totalNumPages.  (if there are 11 pages and the num end pages was 2,
    // we'd end up at 9 which is where the dots would appear)

    if ((Math.max(high_middle, high_start) + 1) == (totalNumPages - numEndPages)) {
        displayListArr[displayListArr.length] = totalNumPages - numEndPages;
    } else if ((Math.max((currentPageNum + numPostPages), high_start) + 1) < (totalNumPages - numEndPages)) {
        // Put in dots if there'll be a gap.
        displayListArr[displayListArr.length] = -1;
    }

    // Finally, add on the end pages if it hasn't already been covered by the
    // middle or first sections.

    var low_end = Math.max(
        Math.max(high_middle, high_start) + 1, // high_start could actually be greater
        (totalNumPages - numEndPages + 1)
    );


    for (var i = low_end; i <= totalNumPages; i++) {
        displayListArr[displayListArr.length] = i;
    }

    // DONE!!!!  Now we just assemble our return array.

//    alert("currentPageNum: " + currentPageNum);
//    alert("totalNumPages: " + totalNumPages);
//    alert("page1Info (start/end): " + pageInfoArr[1].start + "/" + pageInfoArr[1].end);
//    alert("page2Info (start/end): " + pageInfoArr[2].start + "/" + pageInfoArr[2].end);
//    alert("displayListInfo: " + displayListArr.join(", "));

    return {currentPageNum: currentPageNum, totalNumPages: totalNumPages,
            pageInfoArr: pageInfoArr, displayListArr: displayListArr}

}



function isBlank(str) {
    for(var i = 0; i < str.length; i++) {
        if (!isWhiteSpace(str.charAt(i))) return false;
    }
    return true
};



function isWhiteSpace(ch) {
    return (ch==' ' || ch== '\t' || ch=='\n' || ch=='\r');
}


function trim(str) {
    if (str.length == 0) { return "";}

    str = lTrim(str);
    str = rTrim(str);

    return str;
}

function rTrim(str) {
    var strLen = str.length;
    if (strLen == 0) { return; }

    var index = strLen - 1;

    while(index > -1) {
        if (!isWhiteSpace(str.charAt(index))) {
            str = str.substring(0,index+1);
            break;
        }
        index--;
    }

    return str;

}

function lTrim(str) {
    var strLen = str.length;
    if (strLen == 0) {
        return str;
    }

    var index = 0;
    while (index < strLen) {
        if (!isWhiteSpace(str.charAt(index))) {
            str = str.substring(index, str.length);
            break;
        }
        index++;
    }

    return str;
}

function isLeapYear(year) {
    return (((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0)) ? true : false;
}