/*
 * Search Suggest Box
 *
 * a box that 
 * assumes a XML http request that returns a xml document
<root>
 <headerText>Suggestions for your search...</headerText>  
 <query type="brand" typeName="Manufacturer" >Suggest Query Term 1</query>
 <query type="name" typeName="Product Name" >Suggest Query Term 2</query>
</root>
 *
 * uses the util.js from bc_pmc for getXMLHttpRequest
 */

function SuggestBox() {

    var pRequest; // xml http request
    var pDiv; //the div for suggestbox layer
    var pDivIFrame; //an additional div for iframe trick (to be layed before IE input elements ) 
    var pDebug = false; 
    var pInstanceName = ""; //instance name of this object
    var pSearchURL = ""; // the url to retrieve suggests, including query parameter name
    var pQueryParamName = ""; // the query parameter for the query term
    var pFormname = ""; //form name to submit a query
    var pDivName = ""; //the divs layer id
    var pQueryInput; //the user entered query term
    var pSuggest = new Array; //contains suggest query and type for submitting the result 
    var pLastQuery; //remember the last query term from the input
    var pCurrentSelection = -1; // suggest query term selection

    var pAlignment = 'left'; //alignment of suggestbox to input field
    var pSubmit = true; //submit on enter and click

    var submitted = false;

	//holds html code built from httprequest response
	var responseTextStart  = ''; 
    var responseTextHeader = '';  
    var responseTextRow    = '';
    var responseTextEnd    = '' 
    
    
    this.init = function (searchURL, formname, queryParamName, divName, instanceName, debugMode) {
    
    	pSearchURL = searchURL;
    	pFormname = formname;
    	pQueryParamName = queryParamName;
    	pDivName = divName;
    	pDiv = document.getElementById(divName);
    	pDivIFrame =  document.getElementById(divName + "IFrame"); 
    	pInstanceName = instanceName;
    	pDebug = false;
    	
    	if (pSearchURL == "") {
    		if (pDebug) {alert("no searchurl defined");} return null;
    	} 
    	else if (pInstanceName == "") {
    		if (pDebug) {alert("no instancename defined");}	return null;
    	} 
    	else if (pFormname == "") {
    		if (pDebug) { alert("no formname defined"); }return null;
    	} 
    	else if (pQueryParamName == "") {
    		if (pDebug) {alert("no queryparamname defined");} return null;
    	}
    	else if (pDiv == null) {
    		if (pDebug) {alert("need a div for output");}
    	}
    	
	    //initalize the html used to display inside the suggestBox div
	    //contains placeholders replaced from handleResponse() 
	    responseTextStart = '<table width="100%" border="0" cellpadding="0" cellspacing="0" onMouseDown="' + pInstanceName + '.handleClick();">'; 
        responseTextHeader = '<tr><td class="suggestHeader" nowrap="nowrap" colspan="4">@HeaderText@</td></tr>';  
        responseTextRow    = '<tr class="suggestRow" id="' + pDivName + '_@count@" onMouseOver="' + pInstanceName + '.handleMouseOver(@count@);" onMouseOut="' + pInstanceName + '.handleMouseOut(@count@);"><td class="suggest" nowrap="nowrap">@SuggestQuery@</td><td class="suggest" nowrap="nowrap" width="30%">@SuggestType@</td><td class="suggest" nowrap="nowrap">@SuggestImage@</td><td class="suggest" nowrap="nowrap">@SuggestCountText@</td></tr>';
        responseTextImage  = '<img src="@ImageURL@">'; 
        responseTextEnd    = '</table>' 

    	//get query input field and set handlers
    	pQueryInput = document[pFormname][pQueryParamName];
    	pQueryInput.onkeyup = handleKeyPress;
    	pQueryInput.onfocus = showLayer;
    	pQueryInput.onblur = hideLayer;
    	pQueryInput.setAttribute('autocomplete', 'off');
    	document[pFormname].onsubmit = handleSubmit;
    	
    };
    
    /*
     * set if the form should be submitted on click and enter 
     */
    this.setSubmit = function (submitBehaviour) {
    	if(submitBehaviour)
    	{
    		pSubmit = true; 
    	}
    	else
    	{
    		pSubmit = false; 
    	}
    }
    
    /*
     * set if the form should be submitted on click and enter 
     */
    this.setAlignment = function (alignment) {
    	pAlignment = alignment;  
    }
    
    this.handleClick = function () {
        //todo handle the types like brand
    	if (pSuggest[pCurrentSelection] != undefined) {
        	setSearchTermFromSelection(pSuggest[pCurrentSelection]); 
    		if(pSubmit)
    		{
    			document[pFormname].submit();
    		}
    	}
    };

    this.handleMouseOver = function (pos) {
    	var selEl = getRow(pos);
    	deselect();
    	if (selEl != null) {
    		highlight(selEl);
    		pCurrentSelection = pos;
    	}
    };

    this.handleMouseOut = function (pos) {
    	var selEl = getRow(pos);
    	if (selEl != null) {
    		deselect(selEl);
    		pCurrentSelection = -1;
    	}
    };
    
    this.isVisible = function () {
    	if(pDiv.style.display == "block")
    	{
    		return true; 
    	}
    	else
    	{
    		return false; 
    	}
    };
    
    this.handleSubmitOutSideCall = function () {
    	return handleSubmit();
    }
    
    function handleSubmit() {
        submitted = true;
        hideLayer(); // if(pDiv != null ) pDiv.style.display = "none";
        //todo handle the types like brand
        if (pSuggest[pCurrentSelection] != undefined) {
        	setSearchTermFromSelection(pSuggest[pCurrentSelection]);
        	if(!pSubmit) return false; 
        }
    }; 
    
    function setSearchTermFromSelection(currentSelection) {
    	
    	var suggestType = currentSelection[1];
    	//set quotes to do exact search for the complete suggest for types coming directly
    	//from the index data
    	if(suggestType == 'category' || suggestType == 'brand') {
            document[pFormname][pQueryParamName].value = '"'+currentSelection[0]+'"';
    	} else {
    		//do search with unchanged term for others e.g. (searchTerm = real searches from log)
    		//unspecified = product name
            document[pFormname][pQueryParamName].value = currentSelection[0];
    	}
    }

    function handleKeyPress(evt) {
        evt = evt ? evt : event ? event : null;
        var keyCode = evt.keyCode;
        if (keyCode == 38) {
            moveSelection("up");
        } else if (keyCode == 27) {
            hideLayer();
        } else if (keyCode == 40) {
            moveSelection("down");
        } else {
            var query = pQueryInput.value
            if (pQueryInput.value == "") 
            {
                hideLayer();
                return null;
            }
            if (pLastQuery != query) 
            {
                startAjaxRequest(query);
            }
            pLastQuery = query;
        }
    }; 

    function moveSelection(direction) {
        var pos = pCurrentSelection;
        if (direction == "up") {
            pos--;
        } else {
            pos += 1;
        }
        if (pos < 0) {
            deselect();
            pQueryInput.focus();
            pCurrentSelection = -1;
        } else {
            var selEl = getRow(pos);
            if (selEl != null) {
                deselect();
                highlight(selEl);
                pCurrentSelection = pos;
            }
        }
        var query = pQueryInput.value;
        pQueryInput.value = "";
        pQueryInput.focus();
        pQueryInput.value = query;
    };

    function startAjaxRequest(query) {
        
        var requestURL = pSearchURL + encodeURIComponent(query);
        
      	pRequest = getXmlHttpRequest();
        pRequest.open("GET", requestURL, true);
        pRequest.onreadystatechange = callbackAjaxRequest;
        pRequest.send(null);
        
    };
    
    this.hideLayerOutsideCall = function () {
        hideLayer(); // if (pDiv != null) { pDiv.style.display = "none"; }
    };
    
    function hideLayer() {
        if (pDiv != null) {pDiv.style.display = "none"; }
        if(pDivIFrame != null)
        {
        	pDivIFrame.style.left = "-2000px";
        }
        
    };

    function showLayer() {
        if (pDiv != null && pSuggest != null && pSuggest.length >= 1) {
        	
	     	pDiv.style.display = "block";
	     	
	     	var pos = findPos(pQueryInput);
	     	
	     	pos.push(pQueryInput.offsetHeight); 
	     	pos.push(pQueryInput.offsetWidth);

	     	if( pos != null)
	     	{
				pDiv.style.top=(pos[1]+pos[2]+2)+'px';

				var leftPosOffset = 2; 
		     	if(pAlignment != 'left')
		     	{
		     		//firstChild is the table clientWidth 
		     		leftPosOffset = pQueryInput.clientWidth - pDiv.firstChild.clientWidth + leftPosOffset;  
		     	}
		     	var leftPos = pos[0]+leftPosOffset; 
				pDiv.style.left=(leftPos)+'px';
	     	}

        	//position and resize IFrame behind the box
        	if(pDivIFrame != null)
        	{

	     		pDivIFrame.style.top = pDiv.offsetTop; 
	     		pDivIFrame.style.left = pDiv.offsetLeft;
	     		pDivIFrame.style.height = pDiv.offsetHeight;
	     		pDivIFrame.style.width = pDiv.offsetWidth;
	     		
        	}
        }
    };

	function findPos(obj) {
		var curleft = curtop = 0;
	
		if (obj.offsetParent) {
			do {
				curleft += obj.offsetLeft;
				curtop += obj.offsetTop;
			} while (obj = obj.offsetParent);
			return [curleft,curtop];
		}
	}

    function callbackAjaxRequest() {
        if (submitted == false) {
            if (pRequest.readyState == 4) {
                if ((pRequest.status != 200) || (pRequest.responseXML == null)) {
                    hideLayer();
                    if (pDebug) {
                        alert("Error (" + pRequest.status + "): " + pRequest.statusText + " response: " + pRequest.responseText);
                    }
                } else {
                    handleResponseXML(pRequest.responseXML);
                }
            }
        }
    };

    function fireSuggestCompleted(suggestBoxIsVisible) {
        if (typeof onSuggestCompleted == "function") {
            onSuggestCompleted(suggestBoxIsVisible);
        }
    };

    function handleResponseXML(responseDocument) {
        pCurrentSelection = -1;
         
        var i = 0;
        var element;

        var responseText = responseTextStart;  
        var headerTextNode = responseDocument.getElementsByTagName("headerText")[0];
        if(headerTextNode != null && headerTextNode.firstChild != null && headerTextNode.firstChild.data)
        {
        	responseText += responseTextHeader.replace("@HeaderText@", headerTextNode.firstChild.data); 
        }
        
        //get the query parts
        var queries = responseDocument.getElementsByTagName("query");
        pSuggest = new Array;
        for(i=0;i<queries.length; i++)
        {
        	pSuggestParts = new Array;
        	suggestQuery = queries[i].firstChild.data;
        	if(suggestQuery != null)
        	{
	        	pSuggestParts[0] = suggestQuery; 
    	    	pSuggestParts[1] = queries[i].getAttribute("type");
    	    	pSuggest[i] = pSuggestParts;

    	    	var typeName = queries[i].getAttribute("typeName");
    	    	var highlightedQueryTerm = suggestQuery.replace(new RegExp("(" + pQueryInput.value + ")", "ig"), '<span class="suggestContent">$1</span>');
    	    	
    	    	var responseTextRowReplaced = responseTextRow.replace(/@count@/g, i);
    	    	responseTextRowReplaced = responseTextRowReplaced.replace("@SuggestQuery@", highlightedQueryTerm); 
    	    	responseTextRowReplaced = responseTextRowReplaced.replace("@SuggestType@", typeName);
    	    	
    	    	var countText = queries[i].getAttribute("countText");
    	    	if(countText != null)
    	    	{
        	    	responseTextRowReplaced = responseTextRowReplaced.replace("@SuggestCountText@", countText);
    	    	}
    	    	else
    	    	{
        	    	responseTextRowReplaced = responseTextRowReplaced.replace("@SuggestCountText@", "");
    	    	}
    	    	var imageURL = queries[i].getAttribute("imageURL");
    	    	
    	    	if(imageURL != null && imageURL != "")
    	    	{
        	        var imageReplaced = responseTextImage.replace("@ImageURL@", imageURL);  
        	        responseTextRowReplaced = responseTextRowReplaced.replace("@SuggestImage@", imageReplaced);
    	    	}
    	    	else
    	    	{
        	        responseTextRowReplaced = responseTextRowReplaced.replace("@SuggestImage@", "");
    	    	}

    	    	
    	    	responseText += responseTextRowReplaced; 
        	}
        }
        responseText += responseTextEnd;
          
        if (pSuggest.length >= 1) {
            pDiv.innerHTML = responseText;
            showLayer();
            fireSuggestCompleted(true);
        } else {
            hideLayer();
            pDiv.innerHTML = "";
            fireSuggestCompleted(false);
        }
    };

    function highlight(selEl) {
        selEl.className="suggestHighlight";
    };

    /* deselects an element
       or all if null element is passed  
    */
    function deselect(selEl) {
    	if(selEl != null) {
    		selEl.className="suggest";	
    	}
    	else {
	        for (var i in pSuggest) {
	            selEl = getRow(i);
	            if (selEl != null) {
	                selEl.className="suggest";
	            }
	        }
    	}
    };

    function getRow(pos) {
        var selEl;
        selEl = document.getElementById(pDivName + "_" + pos);
        return selEl;
    };

}; 

