/*
	Glossary Of Terms (GOT)
	
	Dependencies:
		request.js
		domutilities.js
		clientutilities.js
		
	Public Properties:
		WIDTH: width of GOT div
		VOFFSET: vertical distance offset of GOT div from the mouseover location
		HOFFSET: horizontal distance offset of GOT div from the mouseover location
		AUTOLINK: boolean on whether or not to parse the content element, doing a 
				 search & replace on textnodes to create gotlinks 
		AUTOELEMENTIDS: an array of element id strings that will be searched and autolinked.
		ADDHREF2GLOSSARY: boolean; Add an href to the full glossary listing
		
	Manual Usage:
		Set class of <a> to 'gotlink' and set title attribute to term to show
		e.g. <a class="gotlink" title="hardwood">Hardwood</a>
		If ADDHREF2GLOSSARY is set to true and the anchor doesn't have an existing 
		href attribute, one is added to the glossary of terms full listing page.
		
	AutoLink Usage:
		When AUTOLINK is set to true, all text nodes within the 'content' elements
		named in the AUTOELEMENTIDS array are searched for matches in the synonym list,
		if a match is found and the textnode isn't a child of <a>, then it's wrapped in a <a>
		e.g. <a class='gotlink' title='[matchvalue]'>[matchvalue]</a>
	
	Modification: 11/27/2006
	- No longer using title attribute because of native browser behavior. Now using faux 'synonym' attribute.
*/
var GOT = {
    WIDTH: 325,
    VOFFSET: 50,
    HOFFSET: 20,
    AUTOLINK: true,
    AUTOELEMENTIDS: new Array('maincontent'),
    ADDHREF2GLOSSARY: true,
    DEBUG: false,
    BASEURL: '/',
    got_init: function() {
        if (navigator.userAgent.indexOf('Safari') > 0) { return; } // Reject Safari due to poor regex and event handling

        if (GOT.AUTOLINK) {
            //request Synonyms
            Http.get({
                //url: "../got/getAllSynonyms.aspx",
                url: GOT.BASEURL + "got/getAllSynonyms.aspx",
                callback: GOT.createGOTLinks,
                cache: Http.Cache.Get
            });
        }
        else {
            GOT.attachEventsToLinks();
        }
    },

    createGOTLinks: function(xmlreply) {

        if (xmlreply.status != Http.Status.OK) {
            if (GOT.DEBUG) { alert('Ajax call to getAllSynonyms.aspx failed. xmlreply.status = ' + xmlreply.status); }
            return;
        }

        var xmlTerms = xmlreply.responseXML;
        // make sure we have the needed objects
        if (xmlTerms == null || GOT.AUTOELEMENTIDS.length == 0) { return; }

        var synNodes = xmlTerms.documentElement.getElementsByTagName('synonym');
        for (var i = 0; i < GOT.AUTOELEMENTIDS.length; i++) {
            var elToSearch = document.getElementById(GOT.AUTOELEMENTIDS[i])
            if (elToSearch != null) {
                var dtStart = new Date();
                GOT.searchAndreplaceTextNodeWithLinks(elToSearch, synNodes);
                var dtEnd = new Date();
                if (GOT.DEBUG) {
                    alert('searchAndreplaceTextNodeWithLinks took \n ' + ((dtEnd - dtStart) / 1000) + ' seconds for ' + synNodes.length + ' synonyms');
                }
            }
            else {
                if (GOT.DEBUG) {
                    alert('GOT.AUTOELEMENTID of ' + GOT.AUTOELEMENTIDS[i] + ' does not exist.');
                }
            }
        }

        GOT.attachEventsToLinks();

    },

    searchAndreplaceTextNodeWithLinks: function(node, synonyms) {
        if (node.nodeType == 3) { // text node
            //if (node.nodeType == 3) { // text node

            var strNewText = new String(node.data);
            var parent = node.parentNode;
            var bfoundmatches = false;

            // make sure the parent isn't a link or a script tag and there is a 1+ word(s) in the node
            if (parent.nodeName.toLowerCase() != 'a' && parent.nodeName.toLowerCase() != 'script' && (new RegExp('\\w+', 'gi').test(strNewText))) {
                //if(parent.nodeName.toLowerCase() != 'a' && parent.nodeName.toLowerCase() != 'script'){
                for (var i = 0; i < synonyms.length; i++) {
                    var regexstring = '\\b(' + synonyms[i].firstChild.nodeValue + ')\\b';
                    var rex = new RegExp(regexstring, 'gi');
                    // look for a match
                    if (rex.test(strNewText)) {
                        bfoundmatches = true;
                        //strNewText = strNewText.replace(rex, "<a class='gotlink' title='$&'>$&</a>");
                        strNewText = strNewText.replace(rex, "<a class='gotlink' synonym='$&'>\$&</a>");
                    }
                }
                if (bfoundmatches) {
                    // replace old text node with new node
                    var newNode = document.createElement('span');
                    newNode.innerHTML = strNewText;
                    parent.replaceChild(newNode, node);
                }
            }
        }
        else {
            // Not a Text node, loop through its children
            // and recursively call this function on each child.
            var kids = node.childNodes;
            for (var i = 0; i < kids.length; i++) {
                GOT.searchAndreplaceTextNodeWithLinks(kids[i], synonyms);
            }
        }
    },

    attachEventsToLinks: function() {
        // get links with gotlink class and attache mouse events
        var lnks = document.getElementsByTagName('a');
        for (var i = 0; i < lnks.length; i++) {
            if (lnks[i].className.indexOf('gotlink') != -1) {
                var lnk = lnks[i];
                // make sure they have a title attribute
                //if(lnk.getAttribute('title') && lnk.getAttribute('title') != ''){
                if (lnk.getAttribute('synonym') && lnk.getAttribute('synonym') != '') {
                    addEvent(lnk, 'mouseover', GOT.getGot);
                    addEvent(lnk, 'mouseout', GOT.killGot);

                    // add href to full glossary if a href hasn't been defined
                    if ((GOT.ADDHREF2GLOSSARY) && (lnk.getAttribute('href') == null || lnk.getAttribute('href') == '')) {
                        //lnk.setAttribute('href', '../how_to/glossary.aspx#' + escape(lnk.getAttribute('title').toLowerCase()));
                        lnk.setAttribute('href', GOT.BASEURL + 'how_to/glossary.aspx#' + escape(lnk.getAttribute('synonym').toLowerCase()));
                    }
                }
            }
        }
    },

    killGot: function() {
        var elGot = document.getElementById('got');
        if (elGot == null || typeof elGot == 'undefined') { return; }
        var parent = elGot.parentNode
        if (typeof parent != "undefined") { parent.removeChild(elGot); }
        else { elGot.style.display = 'none'; }
    },

    getGot: function(e) {
        var target = window.event ? window.event.srcElement : e ? e.target : null;
        var evt = e || window.event;

        // accomodate for image inside of <a>
        while (target.className.indexOf('gotlink') == -1) {
            target = target.parentNode;
        }
        // get the synonym
        //var synonym = target.getAttribute('title');
        var synonym = target.getAttribute('synonym');

        // store the mouse coordinates of this mouseover
        target.setAttribute('mousex', e.clientX);
        target.setAttribute('mousey', e.clientY);

        // XMLHTTPRequest for this link
        //TODO: I may need to kill/cancel any existing requests at this time
        if ((Http != null)) { Http.Init(); }

        Http.get({
            //url: "../got/getTermDetails.aspx?synonym=" +  escape(synonym.toLowerCase()),
            url: GOT.BASEURL + "got/getTermDetails.aspx?synonym=" + escape(synonym.toLowerCase()),
            callback: GOT.fillGot,
            cache: Http.Cache.Get
        }, [target]);
    },

    fillGot: function(xmlreply, elLink) {
        GOT.killGot();

        if (xmlreply.status == Http.Status.OK) {

            //this is the main div
            var elDiv = document.createElement('div');
            elDiv.setAttribute('id', 'got');
            // set the width
            elDiv.style.width = GOT.WIDTH + 'px';

            // set the position
            //GOT.setPosition(parseInt(elLink.getAttribute('mousex')), parseInt(elLink.getAttribute('mousey')), elDiv);
            elDiv.style.top = GOT.calculateTopPosition(elLink) + 'px';
            elDiv.style.left = GOT.calculateLeftPosition(elLink) + 'px';

            // insert the response for the synonym into the div
            //elDiv.innerHTML = xmlreply.responseText;
            //add to <body>
            //elLink.appendChild(elDiv);
            document.body.appendChild(elDiv);

            // add suicide mouseout
            addEvent(elDiv, 'mouseout', GOT.killGot);
            //alert(elDiv.offsetHeight);



            //add header
            var divHeaderGot = document.createElement('div');
            divHeaderGot.setAttribute('id', 'divHeaderGot');
            elDiv.appendChild(divHeaderGot);

            //add middle content
            var divMiddleGot = document.createElement('div');
            divMiddleGot.setAttribute('id', 'divMiddleGot');
            //add the text, and the br tag is for ie...
            divMiddleGot.innerHTML = xmlreply.responseText + '<br style="font-size:0.02em;"/>';
            //alert(divMiddleGot.innerHTML);
            elDiv.appendChild(divMiddleGot);


           

            //add footer
            var divFooterGot = document.createElement('div');
            divFooterGot.setAttribute('id', 'divFooterGot');
            elDiv.appendChild(divFooterGot);

        }
        else {
            if (GOT.DEBUG) {
                alert('Ajax call to getTermDetails.aspx failed. xmlreply.status = ' + xmlreply.status);
            }
        }
        /*
        elLink.onclick = function(){
        var msg = '';
        //msg += 'elLinkID=' + elLink.id;
        msg+= '\n elLink X=' + findPosX(elLink) + ', elLink Y=' + findPosY(elLink) ;
        msg+= '\n getWindowDimensions().height=' + getWindowDimensions().height + ', getWindowDimensions().width=' + getWindowDimensions().width;
        msg+= '\n getWindowHeight()=' + getWindowHeight();
        msg+= '\n elLink.getAttribute(mousex)=' + elLink.getAttribute('mousex') + ', elLink.getAttribute(mousey)=' + elLink.getAttribute('mousey');
        msg+= '\n elDiv.style.top=' + elDiv.style.top + ', elDiv.style.left=' + elDiv.style.left;
        alert(msg);
        };
        */
    },

    calculateLeftPosition: function(elLink) {
        var leftPos = 0;
        //var linkStartX = findPosX(elLink); // do I need this var?
        //var scrollLeftAmount = getDocumentScrollAmount().left;
        var mouseX = parseInt(elLink.getAttribute('mousex'));
        var canvasWidth = getWindowDimensions().width;
        // Left or right?

        if ((mouseX + GOT.WIDTH + GOT.HOFFSET) > canvasWidth) {
            // not enough room to the right of the mouse
            // add extra offset to left
            leftPos = mouseX - GOT.WIDTH - (GOT.HOFFSET * 2);
        }
        else {
            // default, place to the right of mouse
            // there's enough room on the right
            leftPos = mouseX + GOT.HOFFSET; // move 20px to the right or the mouse position
        }
        return leftPos;
    },

    calculateTopPosition: function(elLink) {
        var topPos = 0;
        var canvasHeight = getWindowDimensions().height;
        var scrollTopAmount = getDocumentScrollAmount().top;
        //var linkStartY = findPosY(elLink); // do I need to use this var?
        var mouseY = parseInt(elLink.getAttribute('mousey'));

        if ((mouseY - GOT.VOFFSET) < 1) {
            // mouse is too close to the top, position at top of viewport
            topPos = scrollTopAmount;
        }
        else if ((canvasHeight - mouseY) < GOT.VOFFSET) {
            // mouse is too close to the bottom, add extra offset
            topPos = mouseY - GOT.VOFFSET * 2 + scrollTopAmount;
        }
        else {
            // default
            topPos = mouseY - GOT.VOFFSET + scrollTopAmount;
        }
        return topPos;
    }
}
addEvent(window, 'load', GOT.got_init);


//setTimeout('GOT.got_init();', 5000);

//addEvent(window, 'load', setTimeout('GOT.got_init();', 5000));

//GOT.got_init();
// optional property override usage

//GOT.WIDTH = 300;
//GOT.VOFFSET =  50;
//GOT.HOFFSET = 20;
//GOT.AUTOLINK = true;
//GOT.AUTOELEMENTIDS = new Array('maincontent','contentleft');
//GOT.ADDHREF2GLOSSARY = true;
