﻿// object: wrapper
var GlossaryListing = {};

// object: params
GlossaryListing.Params = {
    WebServiceUrl: null,
    ByLetterID: "GlossaryByLetter",
    ByLetterTermsPerPage: 5,
    ByKeywordsID: "GlossaryByKeywords",
    ByKeywordsTermsPerPage: 5,
    TypePrefix: "Type_"
};

// function: Initialize the "By Letter" glossary view
GlossaryListing.InitByLetter = function (targetID, serviceUrl, termsPerPage) {
    var GL = GlossaryListing,
        params = GL.Params,
        target = $("#" + targetID);
    params.ByLetterID = targetID;
    params.WebServiceUrl = serviceUrl;
    params.ByLetterTermsPerPage = termsPerPage;
    target.find(".LetterFilter").bind('click', GL.LetterFilter_Click);
};

// function: Initialize the "By Keywords" glossary view
GlossaryListing.InitByKeywords = function (targetID, serviceUrl, termsPerPage) {
    var GL = GlossaryListing,
        params = GL.Params,
        target = $("#" + targetID);
    params.ByKeywordsID = targetID;
    params.WebServiceUrl = serviceUrl;
    params.ByKeywordsTermsPerPage = termsPerPage;
    target.find(".TypeFilter").bind('click', {Target: target}, GL.KeywordFilter_Click);
    target.find(".KeywordFilter").bind('click', {Target: target}, GL.KeywordFilter_Click);
};

// function (event): LetterFilter has been clicked
GlossaryListing.LetterFilter_Click = function (e) {
    var GL = GlossaryListing;
    $("#" + GL.Params.ByLetterID).find(".LetterFilter").removeClass("Active");
    $(this).addClass("Active");
    GlossaryListing.RetrieveResultsByLetter($(this).text());
};

// function (ajax): Asynchronously get results for letter filter
GlossaryListing.RetrieveResultsByLetter = function (letter) {
    var GL = GlossaryListing,
        params = GL.Params;
    $.ajax({
        type: "POST",
        url: params.WebServiceUrl + "/GetGlossaryTermsByLetter",
        contentType: "application/json; charset=utf-8",
        data: "{Letter:\"" + letter + "\"}",
        dataType: "json",
        success: function (results) { GL.ShowResults(results, letter, params.ByLetterID, params.ByLetterTermsPerPage) }
    });
};

// function (event): KeywordFilter has been clicked
GlossaryListing.KeywordFilter_Click = function (e) {
    var GL = GlossaryListing,
        target = e.data.Target,
        keywordArray = [];
        
    $(this).toggleClass("Active");
    
    target.find(".Active").each( function (i) {
        if($(this).hasClass("TypeFilter"))
        {
            keywordArray[keywordArray.length] = GL.Params.TypePrefix + $(this).text();
        }
        else
        {
            keywordArray[keywordArray.length] = $(this).text();
        }
    });
    
    if (keywordArray.length > 0)
    {
        $(".NoResults").remove();
        GlossaryListing.RetrieveResultsByKeywords(keywordArray);
    }
    else
    {
        //no active keywords -> clear results
        target.find(".Results").html("");
        target.find(".CurrentSelection").html("");
        target.find(".Pager").html("");
    }
};

// function (ajax): Asynchronously get results for keyword filter
GlossaryListing.RetrieveResultsByKeywords = function (keywords) {
    var GL = GlossaryListing,
        params = GL.Params;
    $.ajax({
        type: "POST",
        url: params.WebServiceUrl + "/GetGlossaryTermsByKeywords",
        contentType: "application/json; charset=utf-8",
        data: "{Keywords:" + GL.StringifyArray(keywords) + "}",
        dataType: "json",
        success: function (results) { GL.ShowResults(results, keywords, params.ByKeywordsID, params.ByKeywordsTermsPerPage) }
    });
};

// function: Asynchronous callback to interpret results and inject into DOM
GlossaryListing.ShowResults = function (results, criteria, targetID, termsPerPage) {
    var terms = results.d,
        GL = GlossaryListing,
        GP = GlossaryPopups,
        params = GL.Params,
        container = $("#" + targetID),
        target = container.find(".Results"),
        currListing, currTerm, html;

    // show filter criteria
    if ($.isArray(criteria))
    {
        criteria = GL.StringifyArrayForDisplay(criteria);
    }
    else
    {
        criteria = "<b>" + criteria + "</b>";
    }
    container.find(".CurrentSelection").html(criteria);
        
    if (terms && terms.length > 0)
    {
        //Clear previous results
        target.html("");
        container.find(".Pager").html("");
        
        for (var i = 0; i < terms.length; i++) //foreach returned term
        {
            // append term and description
            target.append("<div class='GlossaryListing'></div>");
            currListing = target.find(".GlossaryListing:last");
            currTerm = terms[i];
            html =  "<h2>" + 
                        "<span class='GlossaryTerm'>" + currTerm.Term + "</span>" +
                    "</h2>" +
                    "<p>" + currTerm.Definition + "</p>";
            currListing.append(html);
        }

        //if applicable, apply paging
        if (terms.length > termsPerPage)
        {
            GL.InitPaging(container, terms.length, termsPerPage);
        }
        else
        {
            target.find(".Pager").html("");
            target.find(".GlossaryListing").show();
        }
        if (GP)
        {
            GP.Init();
        }
        
    }
    else //terms null or no terms returned
    {
        target.html("").append("<div class='NoResults'>No results found.</div>");
        container.find(".Pager").html("");
    }
};

// function: Initialize paging: Display paging controls, bind events, load first page
GlossaryListing.InitPaging = function (container, numResults, pageSize) {
    var GL = GlossaryListing,
        numPages = Math.ceil(numResults / pageSize), 
        pager = container.find(".Pager"),
        pagingData = {
            Container: container,
            PageSize: pageSize,
            NumPages: numPages
        };
    pager.append("<div class='PagerPrev'></div>");
    for (var i = 0; i < numPages; i++)
    {
		if (i < numPages - 1) {
			pager.append("<div class='PageNum'>" + (i+1) + "</div>");
		} else {
			pager.append("<div class='PageNum' style='margin-right:0px'>" + (i+1) + "</div>");
		}
    }
    pager.append("<div class='PagerNext'></div>");
    //since floating right, need to reverse the order of the elements
    pager.each( function (i) {
        $(this).children().each (function (i) {
            $(this).prependTo( $(this).parent() );
        });
    });
    pager.find(".PageNum").each( function (i) {
        $(this).bind('click', pagingData, GL.PageNum_Click);
    });
    pager.find(".PagerPrev").bind('click', pagingData, GL.PagerPrev_Click);
    pager.find(".PagerNext").bind('click', pagingData, GL.PagerNext_Click);
    
    GL.ShowPage(container, 0, pageSize);
};

// function (event): A page number has been clicked
GlossaryListing.PageNum_Click = function (e) {
//    var container = e.data.Container;
//    container.find(".PageNum").removeClass("CurrPage");
//    $(this).addClass("CurrPage");
    GlossaryListing.ShowPage(e.data.Container, parseInt($(this).text(), 10) - 1, e.data.PageSize);
};

GlossaryListing.PagerPrev_Click = function (e) {
    var data = e.data,
        container = data.Container,
        pageSize = data.PageSize,
        numPages = data.NumPages,
        pagerItems = container.find(".Pager div"),
        activePage = parseInt(pagerItems.filter(".CurrPage:first").text(), 10),
        prevPageNum = (activePage - 2 < 0) ? numPages - 1 : activePage - 2;
    GlossaryListing.ShowPage(container, prevPageNum, pageSize);
};

GlossaryListing.PagerNext_Click = function (e) {
    var data = e.data,
        container = data.Container,
        numPages = data.NumPages,
        pagerItems = container.find(".Pager div"),
        activePage = parseInt(pagerItems.filter(".CurrPage:first").text(), 10),
        nextPageNum = (activePage < numPages) ? activePage : 0;
    GlossaryListing.ShowPage(container, nextPageNum, data.PageSize);
};

// function: Show a particular page of results
GlossaryListing.ShowPage = function (container, pageNum, pageSize) {
    var start = pageNum * pageSize,
        listings = container.find(".GlossaryListing"),
        pager = container.find(".Pager"),
        pagerSize;
    // change classes to indicate current page
    pager.find(".CurrPage").removeClass("CurrPage");
    pager.each( function (i) {
        pagerSize = $(this).find(".PageNum").length;
        pager.find("div:eq(" + (pagerSize - pageNum) + ")").addClass("CurrPage");
    });
    listings.hide();
    listings.slice(start, start + pageSize).show();
};

// function: turn array into string for JSON
GlossaryListing.StringifyArray = function (array) {
    var str = "[";
    for (var i = 0; i < array.length; i++)
    {
        str += "\"" + array[i] + "\"";
        if (i < array.length - 1)
        {
            str += ",";
        }
    }
    str += "]";
    return str;
};

// function: turn array into string for display
GlossaryListing.StringifyArrayForDisplay = function (array) {
    var str = "",
        typePrefix = GlossaryListing.Params.TypePrefix;
    for (var i = 0; i < array.length; i++)
    {
        str += "<b>";
        if (array[i].indexOf(typePrefix) == 0)
        {
            str += array[i].substring(typePrefix.length);
        }
        else
        {
            str += array[i];
        }
        str += "</b>";
        if (i < array.length - 1)
        {
            str += ", ";
        }
    }
    return str;
};

// function: Called when GlossaryByLetter module starts. Loads the first letter's results.
GlossaryListing.LoadStartupLetter = function () {
    $("#" + GlossaryListing.Params.ByLetterID).find(".LetterFilter:first").triggerHandler("click");
};

// function: Called when GlossaryByKeywords module starts. If a keyword is supplied,
//              then it loads that keyword. Otherwise, loads the 
GlossaryListing.LoadStartupKeyword = function (keyword) {
    var container = $("#" + GlossaryListing.Params.ByKeywordsID),
        keywords = container.find(".KeywordFilter"),
        types = container.find(".TypeFilter"),
        keywordFound = false;
    if (keyword)
    {
        //look through all keywords to find match
        keywords.add(types).each( function (i) {
            if ($(this).text().toLowerCase() == keyword.toLowerCase())
            {
                //load the data for this keyword
                $(this).triggerHandler("click");
                //show the keywords tab
                $(".Tab:eq(1)").triggerHandler("click");
                keywordFound = true;
                return;
            }
        });
        if (keywordFound)
        {
            return;
        }
    }
	if (types.length == 0) {
		container.find(".TypesContainer").hide();
	}
    // no keyword or keyword not found -> load first
    keywords.eq(0).triggerHandler("click");
};
