dojo.declare("com.mgh.Search", null, {
    constructor: function(configParams) {
        this.xmlDoc;
        this.categories;
        this.letters;
        this.letterBeginEnd;
        this.hasElementsArray;
        this.conditions = '';
        this.page = '';
        this.recordsDisplaying = 0;

        /********************************** Default Variables *****************************************/
        //accept a json object with all necessary constructor values
        this.queryParams = configParams;
		this.filter = configParams.filter;
		this.href = this.queryParams.href;

        // current page: is the ascii code for the letter currently selected
        // lowestNumber: checks how many results are being displayed before the current letter. 1 is for A.
        // linksToDisplay: is how many categories are displayed before the "view all" link and overlay are displayed
		
		this.query;
		
        this.currentPage = 65;
        this.lowestNumber = 1;
        this.highestNumber = 0;
        this.resultsCount = 0;
        this.previousHighest = 0;
        this.results = 0;
        this.linksToDisplay = this.queryParams.links;
        try {
            fadeOutNode('resultsColumn');
            fadeOutNode('filter1');
            fadeOutNode('conditions1');
        } catch (e) {
            console.log(e);
        }
    },

    /********************************** xml methods *****************************************/
    updateQuery: function(params) {
		this.filter = params;
		this.query = this.href + dojo.toJson(params);
		this.getXmlString();
    },

    getXmlString: function() {
        dojo.xhrGet({
            url: this.query,
            handleAs: "text",
            load: function(response, ioArgs) {
                //outside function listening for the data to be ready
                searchDataReady(response);
                return response;
            },
            error: function(response, ioArgs) {
                alert("An error occurred, with response: " + response);
                return response;
            }
        });
    },

    loadXmlString: function(txt) {
        var Doc;
        var parser;
        try //Internet Explorer
		{
            Doc = new ActiveXObject("Microsoft.XMLDOM");
            Doc.async = "false";
            Doc.loadXML(txt);
            return (Doc);
        }
        catch (e) {
            try //Firefox, Mozilla, Opera, etc.
			{
                parser = new DOMParser();
                Doc = parser.parseFromString(txt, "text/xml");
                return (Doc);
            }
            catch (e) { console.log(e.message) }
        }
        return (null);
    },

    handleXml: function() {
        var names = this.xmlDoc.getElementsByTagName("NAME");
        var letter = '';
        var counter = 0;
        var a = '';
        var i;
        var name = '';

        //initialize these class variables every time a new xml document is loaded
        this.letters = new Array();
        this.letterBeginEnd = new Array();
        this.hasElementsArray = new Array();

        // the first time it begins at 1 because this corresponds to the first record, 
        // endLetter is just initialized
        var beginLetter = 1;
        var endLetter = 0;

        for (var x = 65; x < 91; x++) {
            letter = String.fromCharCode(x);
            for (i = 0; i < names.length; i++) {
                name = names[i].childNodes[0].nodeValue;
                if (name.substring(0, 1).toUpperCase() == letter) {
                    endLetter += 1;
                    a += i + ',';
                    //counts the total number of records
                    //this.resultsCount += 1;
                }
            }

            a = a.substring(0, a.length - 1);
            if (a != '') {
                this.hasElementsArray[counter] = x;
                //where "A" begins and "B" ends and so on
                this.letterBeginEnd[letter] = beginLetter + ',' + endLetter;
                //start counting from the next one where you left off
                beginLetter = endLetter + 1;
                counter += 1;
            }
            this.letters[letter] = a;
            a = '';
        }
		
		//doing this does not return the correct number of results
        //this.results = this.resultsCount;
        //this.resultsCount = 0;
		
		this.results = names.length;
    },

    /********************************** data methods *****************************************/
    createGroup: function(start, position) {
        var letter = String.fromCharCode(start);
        var text = '';
        var output = '';
        var condition = '';
        var description = '';

        try {
            var ids = this.letters[letter].split(',');
            if (this.letters[letter] != '') {
                var terms = this.xmlDoc.getElementsByTagName("TERM");
                var names = this.xmlDoc.getElementsByTagName("NAME");
                var conditionIds = this.xmlDoc.getElementsByTagName("METADATA");
                var i;
                var css = '';

                if (position == 1) {
                    css = 'contentRow topBorder clearfix';
                } else {
                    css = 'contentRow clearfix';
                }

                output = '<div class="' + css + '">';
                output += '<p>' + letter + '</p>';
                output += '<div id="resultsGroup">';
                output += '<ul>';

                for (i = 0; i < ids.length; i++) {
                    condition = conditionIds[ids[i]];
					description = this.getNodeData(condition, "Description");

                    if (description == 0) {
                        description = '';
                    } else {
                        text = '<span class="conditionDescription">';
                        text += description;
                        text += '<br><br></span>';
                        description = text;
                    }
                    if (this.queryParams.search == 'conditions') {
                        output += '<li><a href="/conditions/condition.aspx?ID=' +
						this.getConditionId(condition) + '&type=conditions' +
						'">' + names[ids[i]].childNodes[0].nodeValue + '</a>' + description + '</li>';
                    } else {
                        output += '<li><a href="/doctors/doctor.aspx?ID=' +
						this.getPhysicianId(condition) + '">' +
						names[ids[i]].childNodes[0].nodeValue + '</a></li>';
                    }
                }
                output += '</ul>';
                output += '</div>';
                output += '</div>';

            } else {
                output = '';
            }
        } catch (e) {
            output = '';
        }
        return output;
    },

    displayResults: function(id, type, year) {
        var i;
        var text = '';
        var output = '';
        var condition = '';
        var letter = '';
        var nextLetter = '';
        var css = '';
        var counter = 0;
        var description = '';
        var clinicalInterest = '';
        var boardCertification = '';
        var physicianTableClass = 'physicianTable';
        var upperLimit;
        var ids;
        var dateYear = '';
        var nextDateYear = '';
        var currentYear;
        var jtg1Flag = 0;


        if (type != 'letter') {
            upperLimit = id + this.queryParams.numPerPage;
        } else {
            //this is the point where elements can be sorted by date. 
            letter = String.fromCharCode(id);
            ids = this.letters[letter].split(',');
            if (this.letters[letter] != '') {
                id = parseInt(ids[0]);
                upperLimit = id + ids.length;
            }
        }

        var elements = new Array();
        var terms = this.xmlDoc.getElementsByTagName("TERM");
        var names = this.xmlDoc.getElementsByTagName("NAME");
        var conditionIds = this.xmlDoc.getElementsByTagName("METADATA");

        for (i = id; i < upperLimit; i++) {
            try {
                //setting the year to 0 displays all results, this could be used for all searches,
                //use this try statement to detect whether the date parameter is present

                //to sort elements by date it is necessary to sort the letters[letter} array first by date, then
                //instead of getting conditionIds[i], we use conditionIds[sortedArray[i]] then all things will be fine
                try {
                    dateYear = this.getNodeData(conditionIds[i], 'Date').split('/')[2];
                    dateNextYear = this.getNodeData(conditionIds[i + 1], 'Date').split('/')[2];
                    if (year == 0) {
                        currentYear = dateYear;
                        dateNextYear = dateYear;
                    } else {
                        currentYear = year;
                    }
                } catch (en) {
                    dateYear = year;
                    currentYear = year;
                    nextYear = year;
                }

                if (dateYear == currentYear) {
                    if (type != 'letter') {
                        letter = names[i].childNodes[0].nodeValue.substring(0, 1);
                        try {
                            nextLetter = names[i + 1].childNodes[0].nodeValue.substring(0, 1);
                        } catch (ex) {
                            nextLetter = names[i].childNodes[0].nodeValue.substring(0, 1);
                        }
                    } else {
                        nextLetter = letter;
                    }

                    if (i == upperLimit - 1) {
                        physicianTableClass = 'physicianTableLast';
                    }

                    condition = conditionIds[i];
					description = this.getNodeData(condition,"Description");

                    //display the first letter
                    if (counter == 0) {
                        output += '<table width="100%" border="0" cellspacing="0" cellpadding="0">';
                        output += '<tr>';
                        output += '<td valign="top" width="30">';
                        output += '<div class="letter">' + letter + '</div>';
                        output += '</td>';
                        output += '<td>';
                        output += '<div id="resultsGroup">';
                    }

					description == 0 ? description = '' : description = description;

					text += '<table width="655" border="0" cellspacing="0" cellpadding="0">';
					text += '<tr>';
					text += '<td class="searchDescription">';
					text += description;
					text += '</td>';
					text += '</tr>';
					text += '</table>';

					description = text;

					output += '<div><a href="http://www.massgeneral.org/conditions/condition.aspx?ID=' +
					//this.getConditionId(condition) + '&type=' + this.getHierarchyType(terms[i]) + 
						this.getConditionId(condition) + '&type=conditions' +
						'">' + names[i].childNodes[0].nodeValue + '</a>' + description + '</div>';
						
                    description = '';
                    text = '';
                    //display changing letters

                    if (letter != nextLetter) {
                        output += '</div>';
                        output += '</div>';
                        output += '</td>';
                        output += '</tr>';
                        output += '</table>';
                        output += '<br/><br/>';
                        output += '<table width="100%" border="0" cellspacing="0" cellpadding="0">';
                        output += '<tr>';
                        output += '<td valign="top" width="30">';
                        output += '<div class="letter">' + nextLetter + '</div>';
                        output += '</td>';
                        output += '<td>';
                        output += '<div id="resultsGroup">';
                    }
                    counter += 1;
                }

            } catch (e) {
                //console.log(e);
                break;
            }
        }
        output += '<br></div>';
        output += '</td>';
        output += '</tr>';
        output += '</table>';
        this.recordsDislaying = counter;

        if (counter == 0) {
            output = '<div class="noResultsBody" style="border-bottom: none;">\
							<p><b>No results found.</b><br />\
							Deselect one or more categories above to display more results. \
							Or, <a href="#" onclick="dojo.publish(\'clearAllSelections\', [])">clear all selections</a> and try your search again.<br/>\
							To expand your search to the entire Mass General website, use the search box in the top right corner of the page.</p>\
						</div>';
            dojo.byId('descriptions').style.display = 'none';
        } else {
            dojo.byId('descriptions').style.display = 'block';
        }
        return output;
    },

    getHierarchyType: function(node) {
        var type = '';
        try {
            for (var i = 0; i < node.childNodes.length; i++) {
                if (node.childNodes[i].nodeName != '#text') {
                    if (node.childNodes[i].nodeName == 'HIERARCHY') {
                        if (node.childNodes[i].getAttribute("TYPE") == "BT") {
                            try {
                                // works on ie
                                type = node.childNodes[i].childNodes[0].childNodes[0].nodeValue;
                            } catch (ex) {
                                //firefox
                                type = node.childNodes[i].childNodes[1].childNodes[0].nodeValue;
                            }
                            break;
                        }
                    }
                }
            }
        } catch (e) {
            console.log(e);
        }
        return type;
    },

    getConditionId: function(node) {
        var conditionId = 0;
        var field = '';
        try {
            for (var i = 0; i < node.childNodes.length; i++) {
                if (node.childNodes[i].nodeName != '#text') {
                    if (node.childNodes[i].getAttribute("NAME") == "Condition ID") {
                        conditionId = node.childNodes[i].childNodes[0].nodeValue;
                        break;
                    }
                }
            }
        } catch (e) {
            console.log(e);
        }
        return conditionId;
    },

    getNodeData: function(node, attName) {
        var data = '';
        var field = '';
        var regEx;
        try {
            for (var i = 0; i < node.childNodes.length; i++) {
                if (node.childNodes[i].nodeName != '#text') {
                    if (node.childNodes[i].getAttribute("NAME") == attName) {
                        data = node.childNodes[i].childNodes[0].nodeValue;
                        break;
                    }
                }
            }
        } catch (e) {
            //jlp8 08/31/2010 logging to the console slows performance
        }
        return data;
    },

    /********************************** display methods *****************************************/
    //paging functions such as resetHighlights and getNumberOfResults are commented out
    //because this might be a class on its own	
    refreshView: function(num) {
        try {
            this.resetHighlights();
            var letter = String.fromCharCode(num);
            //important, set the current page to the letter. the 'letter' variable tells
            //the script to only process one and re-set all other values
            this.gotoPage(num);
            dojo.byId(letter).className = 'active';
            dojo.byId('ALL').className = 'test';
        } catch (e) {
            console.log(e);
        }
    },

    letterView: function(num) {
        this.resetHighlights();
        var letter = String.fromCharCode(num);
        this.gotoLetter(num);
        dojo.byId(letter).className = 'active';
        dojo.byId('ALL').className = 'test';
    },

    defaultView: function() {
        try {
            this.createAlphaList();
            this.resetHighlights();
            this.gotoPage(0);
            dojo.byId('A').className = 'test';
            dojo.byId('ALL').className = 'active';

        } catch (e) {
            console.log(e);
        }
    },

    /********************************** paging methods *****************************************/
    createAlphaList: function() {
        var output = '<ul><li class="active" id="ALL"><a href="#" onclick="viewAll()">All</a></li>';
        var letter = '';
        var css = 'test';
        var letterCode = 0;
        for (var i = 0; i < 26; i++) {
            letterCode = 65 + i;
            letter = String.fromCharCode(letterCode);
            output += '<li id="' + letter + '" class="' + css + '">';
            if (this.letters[letter] != '') {
                output += '<a href="#" onclick="letterView(' + letterCode + ')">';
                output += letter;
                output += '</a>';
            }
            else {
                output += '<span>' + letter + '</span>';
            }

            output += '</li>';
        }
        output += '</ul>';
        dojo.byId('alphaList').innerHTML = output;
    },

    resetHighlights: function() {
        var nodes = dojo.query('li', 'alphaList');
        for (var i = 0; i < nodes.length; i++) {
            nodes[i].className = 'test';
        }
    },

    toggleDescriptions: function() {
        try {
            var nodes = dojo.query('.searchDescription', 'browseResults');
            for (var i = 0; i < nodes.length; i++) {
                if (nodes[i].style.display == '') {
                    nodes[i].style.display = 'block';
                }
                //console.log(i + ' ' + nodes[i].style.display.toString());
                if (nodes[i].style.display == 'block') {
                    nodes[i].style.display = 'none';
                } else {
                    nodes[i].style.display = 'block';
                }
            }
        } catch (e) {
            console.log(e);
        }
    },

    createPaging: function(start) {
        var pages = this.xmlDoc.getElementsByTagName("TERM").length / this.queryParams.numPerPage;
        var i;
        var css = 'test';
        var lowerPage = 1;
        var higherPage = this.queryParams.numPerPage;

        var numberOfResults = this.getFiftyNumberOfResults(start);
        var resultsDisplay = '<div class="resultNumber" id="numberOfResults">' + numberOfResults + '</div>';

        numberOfResults != '' ? resultsDisplay = resultsDisplay : resultsDisplay = '';

        var output = '';

        //start JTG1
        var pageRange = 15;
        var activePage = 1;
        var lowerBoundry = 1;
        var upperBoundry = pages;
        var controlPage = parseInt(pageRange / 2);
        var lowerRemainder = 0;
        var upperRemainder = 0;

        if (pages > 1) {
            output += '<ul>';
            if (start != 0) {
                output += '<li class="prev"><a href="#" onclick="previousPage()">Previous</a></li>';
                activePage = parseInt(start / this.queryParams.numPerPage);
                activePage = activePage + 1;
            }

            if (activePage - controlPage <= 0) {
                lowerRemainder = controlPage - activePage;
                lowerBoundry = 0;
                upperBoundry = activePage + controlPage + lowerRemainder + 1;
            }
            if (activePage + controlPage > pages) {
                upperRemainder = parseInt(pages) - activePage + 1;
                upperRemainder = controlPage - upperRemainder;
                upperBoundry = pages;
                lowerBoundry = activePage - controlPage - upperRemainder - 1;
            }
            if ((activePage - controlPage > 0) && (activePage + controlPage <= pages)) {
                upperBoundry = activePage + controlPage;
                lowerBoundry = activePage - controlPage - 1;
            }


            if (upperBoundry > pages) { upperBoundry = pages; }
            if (lowerBoundry < 0) { lowerBoundry = 0; }

            //for (i = 0; i < pages; i++){ 
            for (i = lowerBoundry; i < upperBoundry; i++) {
                if (activePage - 1 == i) {
                    output += '<li class="' + css + '" id="page' + i + '"><strong>' + (i + 1).toString() + '</strong></li>';
                }
                else {
                    output += '<li class="' + css + '" id="page' + i + '"><a href="#" onclick="gotoPage(' + (i * this.queryParams.numPerPage) + ')">' + (i + 1).toString() + '</a></li>';
                }

            }
            if (activePage < pages) {
                output += '<li class="next"><a href="#" onclick="nextPage()">Next</a></li>';
            }
            output += '</ul>';
        }
        return resultsDisplay + output;
    },

    createLetterPaging: function(start) {
        var pages = this.xmlDoc.getElementsByTagName("TERM").length / this.queryParams.numPerPage;
        var i;
        var css = 'test';
        var lowerPage = 1;
        var higherPage = this.queryParams.numPerPage;
        var numberOfResults = this.getLetterNumberOfResults(start, 'page');
        var resultsDisplay = '<div class="resultNumber" id="numberOfResults">' + numberOfResults + '</div>';

        output = '';

        //start JTG1
        var pageRange = 15;
        var activePage = 1;
        var lowerBoundry = 1;
        var upperBoundry = pages;
        var controlPage = parseInt(pageRange / 2);
        var lowerRemainder = 0;
        var upperRemainder = 0;

        if (pages > 1) {
            output += '<ul>';
            if (start != 0) {
                output += '<li class="prev"><a href="#" onclick="previousPage()">Previous</a></li>';
                activePage = parseInt(start / this.queryParams.numPerPage);
                activePage = activePage + 1;
            }

            if (activePage - controlPage <= 0) {
                lowerRemainder = controlPage - activePage;
                lowerBoundry = 0;
                upperBoundry = activePage + controlPage + lowerRemainder + 1;
            }
            if (activePage + controlPage > pages) {
                upperRemainder = parseInt(pages) - activePage + 1;
                upperRemainder = controlPage - upperRemainder;
                upperBoundry = pages;
                lowerBoundry = activePage - controlPage - upperRemainder - 1;
            }
            if ((activePage - controlPage > 0) && (activePage + controlPage <= pages)) {
                upperBoundry = activePage + controlPage;
                lowerBoundry = activePage - controlPage - 1;
            }


            if (upperBoundry > pages) { upperBoundry = pages; }
            if (lowerBoundry < 0) { lowerBoundry = 0; }

            for (i = lowerBoundry; i < upperBoundry; i++) {
                if (activePage - 1 == i) {
                    output += '<li class="' + css + '" id="page' + i + '"><strong>' + (i + 1).toString() + '</strong></li>';
                }
                else {
                    output += '<li class="' + css + '" id="page' + i + '"><a href="#" onclick="gotoPage(' + (i * this.queryParams.numPerPage) + ')">' + (i + 1).toString() + '</a></li>';
                }

            }
            if (activePage < pages) {
                output += '<li class="next"><a href="#" onclick="nextPage()">Next</a></li>';
            }
            output += '</ul>';
        }
        return resultsDisplay;
    },

    getLetterNumberOfResults: function(startLetter, flag) {
        var i;
        var top = 0;
        var count = 0;
        var output = '';
        var total = 0;
        try {
            if (flag == 'page') {
                //how many letters to display per page
                top = 1;
                //look for the first letter to have elements and stop when found
                for (i = 0; i < this.hasElementsArray.length; i++) {
                    for (var x = startLetter; x < startLetter + top; x++) {
                        if (this.hasElementsArray[i] == x) {
                            this.lowestNumber = parseInt(this.letterBeginEnd[String.fromCharCode(x)].split(",")[0]);
                            break;
                        }
                    }
                    //break this loop, find a way of breaking all loops from the nested loop
                    if (this.hasElementsArray[i] == x) {
                        break;
                    }
                }
                //count the highest numbers on each available elements
                for (i = 0; i < top; i++) {
                    if (this.letters[String.fromCharCode(startLetter + i)] != '') {
                        total += parseInt(this.letters[String.fromCharCode(startLetter + i)].split(",").length);
                    }
                }

                this.highestNumber = this.lowestNumber + total;
            }
            else {
                this.lowestNumber = parseInt(this.letterBeginEnd[String.fromCharCode(this.currentPage)].split(",")[0])
                this.highestNumber = parseInt(this.letterBeginEnd[String.fromCharCode(this.currentPage)].split(",")[1]);
            }
            if (this.results > 0) {
				var n = this.highestNumber - this.lowestNumber
				var s = n >1 ? 's' : '';
				output += n.toString();
                output += ' Result' + s;
				
            } else {
                output = '';
            }
        }
        catch (e) {
            output = '';
        }
        return output;
    },

    getFiftyNumberOfResults: function(start) {
        var output;
        var end;
        var format = '<strong>${0} to ${1}</strong> of ${2} results';
        var singleResultFormat = '<strong>${0}</strong> result${1}';
        var s = 's';

        if (this.results > 0) {
            start += 1;
            start == 1 ? end = this.queryParams.numPerPage : end = start + (this.queryParams.numPerPage - 1);

            if (end >= this.results) {
                end = this.results;
            }
            if (start != end) {
                output = dojo.string.substitute(format, [start, end, this.results]);
            } else {
                s = start > 1 ? 's' : '';
                output = dojo.string.substitute(singleResultFormat, [start, s]);
            }
        } else {
            output = '<strong>0</strong> results';
        }
        return output;
    },	

    /********************************** paging navigation *****************************************/
    gotoPage: function(start) {
        var page = this.displayResults(start, '', 0);
        this.currentPage = start;
        var paging = this.createPaging(start);
        dojo.byId('browseResults').innerHTML = page;
        this.resetHighlights();
        dojo.byId('ALL').className = 'active';
        dojo.byId('pagingTop').innerHTML = paging;
        dojo.byId('pagingBottom').innerHTML = paging;
    },

    gotoLetter: function(start) {
        var page = this.displayResults(start, 'letter', 0);
        var paging = this.createLetterPaging(start);
        this.resetHighlights();
        dojo.byId('browseResults').innerHTML = page;
        dojo.byId('pagingTop').innerHTML = paging;
        dojo.byId('pagingBottom').innerHTML = paging;
    },

    nextPage: function() {
        var page = this.currentPage + this.queryParams.numPerPage;
        if (page < this.results) {
            this.gotoPage(page);
        }
    },

    previousPage: function() {
        var page = this.currentPage - this.queryParams.numPerPage;
        if (page < 0) {
            page = 0;
        }
        this.gotoPage(page);
    }
});        // JavaScript Document
