/**
 * SpexLive AutoComplete JavaScript Library.
 * This file binds events required for AutoComplete feature and contains methods used in Autocomplete.
 * 
 * @version 1.0.0
 * @author: Waqas Memon (wmemon@etilizepak.com)
 * 			Etilize Pvt. Ltd. (A GFK Product Data Company) 
 */



function SpexLiveAutoComplete(){
	/**
	 * Handle $ sign conflict between jQuery & prototype.
	 */
	this.JQ = jQuery.noConflict();
			
	this.autoCompleteSuggestionsBox = "suggestionsBox";
	this.autoSuggestionsList = "autoSuggestionsList";

	spxautocompleteconfig.autoCompleteField = "#"+spxautocompleteconfig.autoCompleteField;
	
	//on DOM ready
	this.JQ(document).ready(function() {
		
		/**
		 * Locale is the language and country code the website is working with. This can be hard-coded as it is, or you can select value of 
		 * any hidden field and/or html select/combo, etc. 
		 * 
		 ******************************************************************************************************************************/
		// TODO: CHANGE FOLLOWING CODE, IF AND ONLY IF YOU WANT TO CHANGE DEFAULT IMPLEMENTATION OF HANDLING MULTIPLE LOCALES..
		if(spxautocomplete.JQ("#"+spxautocompleteconfig.localeField) && spxautocomplete.JQ("#"+spxautocompleteconfig.localeField).val() !==""){
			//This will set locale to the value of the html input/select field
			spxautocompleteconfig.LOCALE = spxautocomplete.JQ("#"+spxautocompleteconfig.localeField).val();
			
			//This binds an onchange event to html input/select field to change the value of the locale on the run. 
			spxautocomplete.JQ("#"+spxautocompleteconfig.localeField).change(function(){
				spxautocompleteconfig.LOCALE = spxautocomplete.JQ("#"+spxautocompleteconfig.localeField).val();
			});
		}		
		
		if(!spxautocompleteconfig.LOCALE || spxautocompleteconfig.LOCALE == ""){
			//TODO: If you store selected site locale in any other way then input hidden field, please implement it here by yourself.
			spxautocompleteconfig.LOCALE = spxautocompleteconfig.defaultLocale;
		}			
		/******************************************************************************************************************************/
		
		
		//This will add ignoreme text field in DOM which will be used for crawler detection.
		spxautocomplete.prototype.blockCrawling();
		
		this.currentSelection = -1;
		this.currentValue = '';
		this.oldValue = '';
		//added timeout to handle keypress and hold problem, also limiting requests when user wants to type words.
		var hitTimeOut = null;
		spxautocomplete.JQ(spxautocompleteconfig.autoCompleteField).keyup(function(e) {
			//pageUp, pgDown, insert, home, end, arrow keys, 
			if(!(e.which > 32 &&  e.which < 46)) {
				if(hitTimeOut)
		            clearTimeout(hitTimeOut);
		
				//timeout found after a little research, appears to derive from Neilsen as 100ms
				//References: http://stackoverflow.com/questions/4255027/what-is-a-good-timeout-for-autocomplete-results
				hitTimeOut = setTimeout(function(){spxautocomplete.prototype.bindKeypressEvent(e);}, 150);
				
			}
		});


		spxautocomplete.prototype.addListBoxToDOM();
		
		spxautocomplete.JQ(spxautocompleteconfig.autoCompleteField).blur(function(e) {
			spxautocomplete.prototype.fill(spxautocomplete.JQ(spxautocompleteconfig.autoCompleteField).val());
		});

		spxautocomplete.prototype.bindListEvent();		
	});
	
}
var spxautocomplete = new SpexLiveAutoComplete();


spxautocomplete.prototype = {

    /**
    * This method will block crawler traffic on text field by adding a dummy text field in form to fool the crawler. 
    */
    blockCrawling: function() {
        //TODO: insert after parent may cause issues when input element's immediate parent is form.
        spxautocomplete.JQ('<input type="text" id="ignoreme"/>').insertAfter(spxautocomplete.JQ(spxautocompleteconfig.autoCompleteField).parent());

    },

    /**
    * This method checks if the DOM has been loaded and if its ready, it binds events with input text field<br>
    * and LI list items for keyboard and mouse navigation.  
    */

    addListBoxToDOM: function() {
        spxautocomplete.JQ('<br/><div class="' + spxautocompleteconfig.suggestionBoxCSSClass + '" id="' + spxautocomplete.autoCompleteSuggestionsBox + '" style="display: none;" >'
					+ '<div class="' + spxautocompleteconfig.suggestionListCSSClass + '" id="' + spxautocomplete.autoSuggestionsList + '"></div>'
					+ '</div>').insertAfter(spxautocompleteconfig.autoCompleteField);
    },

    /**
    * Autocomplete event for input field,
    */
    bindKeypressEvent: function(e) {
        if (e.which == 27) {
            spxautocomplete.prototype.fill(spxautocomplete.JQ(spxautocompleteconfig.autoCompleteField).val());
        }
        else
            if (e.which == 13) { //Enter or escape
                window.location.href = "/eGen/cnt/IBAShop/Search_Etilize.asp?srkeys=" + escape(unFixQuotes(spxautocomplete.JQ(spxautocompleteconfig.autoCompleteField).val())) + "&contract=" + window.document.getElementById("contract").value;
            return false;
        } else {
            var newValue = spxautocomplete.JQ(spxautocompleteconfig.autoCompleteField).val();
            if (spxautocomplete.oldValue !== newValue) {
                spxautocomplete.oldValue = spxautocomplete.JQ(spxautocompleteconfig.autoCompleteField).val();
                spxautocomplete.prototype.lookup(spxautocomplete.oldValue);
            }
        }
    },

    /**
    * Navigation events for List of suggestions
    */
    bindListEvent: function() {
        spxautocomplete.JQ(document).keyup(function(e) {
            switch (e.keyCode) {
                case 38: // User pressed "up" arrow
                    spxautocomplete.prototype.navigate('up');
                    break;
                case 40: // User pressed "down" arrow
                    spxautocomplete.prototype.navigate('down');
                    break;
                case 13: // User pressed "enter"
                    if (spxautocomplete.currentValue != '') {
                        spxautocomplete.JQ(spxautocompleteconfig.autoCompleteField).text(spxautocomplete.currentValue);
                        spxautocomplete.currentSelection = -1;
                        spxautocomplete.currentValue = "";
                    }
                    break;
            }
        });
    },

    /**
    * This will handle hover event caused by mouse
    */
    bindHoverEvent: function() {
        // Add data to let the hover know which index they have
        for (var i = 0; i < spxautocomplete.JQ("#" + spxautocomplete.autoSuggestionsList + " li").size(); i++) {
            spxautocomplete.JQ("#" + spxautocomplete.autoSuggestionsList + " li").eq(i).data("number", i);
        }
        // Simulate the "hover" effect with the mouse
        spxautocomplete.JQ("#" + spxautocomplete.autoSuggestionsList + " li").hover(
				function() {
				    spxautocomplete.currentSelection = spxautocomplete.JQ(this).data("number");
				    spxautocomplete.prototype.setSelected(spxautocomplete.currentSelection);
				}, function() {
				    spxautocomplete.JQ("#" + spxautocomplete.autoSuggestionsList + " li").removeClass(spxautocompleteconfig.listItemHoverClass);
				    spxautocomplete.currentValue = '';
				}
			);


    },


    /**
    * This method sends cross-domain AJAX requests for the provided input.
    * @param value
    */
    lookup: function(value) {
        if (spxautocomplete.JQ.trim(value).length < 2) {
            spxautocomplete.JQ("#" + spxautocomplete.autoCompleteSuggestionsBox).hide();
        } else {
            if (spxautocomplete.JQ("#ignoreme").val() == '') {
                spxautocomplete.prototype.crossDomainAJAX(value);
                spxautocomplete.currentSelection = -1;
                spxautocomplete.currentValue = "";
            }
        }
    },


    /**
    * This method fills the input text field with the value selected from list.
    * @param value
    * 
    */
    fill: function(value) {
        spxautocomplete.JQ(spxautocompleteconfig.autoCompleteField).val(unFixQuotes(value));
        setTimeout("spxautocomplete.JQ('#" + spxautocomplete.autoCompleteSuggestionsBox + "').hide();", 150);
    },

    /**
    * This mehtod sends cross-domain AJAX request and returns a JSON object in a callback() method.
    * @param value
    * 
    */
    crossDomainAJAX: function(value) {
        var serverURL = spxautocompleteconfig.serverURL + "&maxSize=" + spxautocompleteconfig.RESPONSE_KEYWORDS_SIZE + "&value=" + encodeURIComponent(value) + "&authKey=" + spxautocompleteconfig.AUTH_KEY + "&locale=" + spxautocompleteconfig.LOCALE;

        jQuery.ajax({
            url: serverURL,
            dataType: "jsonp",
            jsonp: 'spxautocomplete.prototype.callback',
            success: function(json) {
                spxautocomplete.prototype.callback(json);
            }
        });


    },

    /**
    * This will handle events caused by keyboard navigation
    * @param direction
    * 
    */
    navigate: function(direction) {
        // Check if any of the menu items is selected
        if (spxautocomplete.JQ("#" + spxautocomplete.autoSuggestionsList + " li." + spxautocompleteconfig.listItemHoverClass + "").size() == 0) {
            spxautocomplete.currentSelection = -1;
        }
        if (direction == 'up') {
            if (!(spxautocomplete.currentSelection <= 0)) {
                spxautocomplete.currentSelection--;
            } else {
                spxautocomplete.currentSelection = spxautocomplete.JQ("#" + spxautocomplete.autoSuggestionsList + " li").size() - 1;
            }
        } else if (direction == 'down') {
            if (spxautocomplete.currentSelection != spxautocomplete.JQ("#" + spxautocomplete.autoSuggestionsList + " li").size() - 1) {
                spxautocomplete.currentSelection++;
            } else {
                spxautocomplete.currentSelection = 0;
            }
        }
        spxautocomplete.prototype.setSelected(spxautocomplete.currentSelection);
    },

    /**
    * This method maintains the navigation selected item
    * @param menuitem
    * 
    */
    setSelected: function(menuitem) {
        spxautocomplete.JQ("#" + spxautocomplete.autoSuggestionsList + " li").removeClass(spxautocompleteconfig.listItemHoverClass);
        spxautocomplete.JQ("#" + spxautocomplete.autoSuggestionsList + " li").eq(menuitem).addClass(spxautocompleteconfig.listItemHoverClass);
        spxautocomplete.currentValue = spxautocomplete.JQ("#" + spxautocomplete.autoSuggestionsList + " li").eq(menuitem).attr("onclick");
        spxautocomplete.JQ(spxautocompleteconfig.autoCompleteField).val(spxautocomplete.JQ("#" + spxautocomplete.autoSuggestionsList + " li").eq(menuitem).text());
    },

    /**
    * The callback method is returned in JSON from AJAX which executes itself as soon as response arrives.
    * @param data
    * @return
    */
    callback: function(data) {
        var error;
        if (data.error) {
            error = true;
        }

        if (!error) {
            var input = spxautocomplete.JQ(spxautocompleteconfig.autoCompleteField).val().toLowerCase();
            if (data.keywordList.length > 0) {
                if (data.keyword.toLowerCase() == input) {
                    var elem = "";
                    spxautocomplete.JQ.each(data.keywordList, function(i, keyword) {
                        var styledKeyword = "";

                        //Adding space in the start of the keyword temporarily.
                        var keyword1 = " " + keyword.keyword.toLowerCase();
                        var inputLenght = input.length;
                        var index = keyword1.indexOf(" " + input);
                        var oldIndex = 0;
                        do {
                            if (index != oldIndex) {
                                if (styledKeyword.length > 0) {
                                    styledKeyword += "" + keyword.keyword.substring(oldIndex + inputLenght, index) + "";
                                } else {
                                    styledKeyword += "" + keyword.keyword.substring(oldIndex, index) + "";
                                }
                            }
                            styledKeyword += "<b>" + keyword.keyword.substring(index, index + inputLenght) + "</b>";
                            oldIndex = index;
                            index = keyword1.indexOf(" " + input, oldIndex + 1);
                        } while (index > -1);

                        styledKeyword += "" + keyword.keyword.substring(oldIndex + inputLenght) + ""
                        elem += "<li id='keywordElement' onmousedown='spxautocomplete.prototype.fill(\"" + fixQuotes(keyword.keyword) + "\"); spxautocompleteconfig.prototype.defaultSearch(\"" + fixQuotes(keyword.keyword) + "\");'>";
                        //elem += "<li id='keywordElement' onclick='spxautocomplete.prototype.fill(\"" + fixQuotes(keyword.keyword) + "\"); spxautocompleteconfig.prototype.defaultSearch(\"" + fixQuotes(keyword.keyword) + "\");'>";
                        //elem += "<li id='keywordElement' onclick='spxautocomplete.prototype.fill(\"" + fixQuotes(keyword.keyword) + "\"); window.location.href = \"/eGen/cnt/IBAShop/Search_Etilize.asp?srkeys=" + fixQuotes(keyword.keyword) + "\";'>";
                        elem += spxautocomplete.JQ.trim(styledKeyword) + "</li>";
                    });

                    spxautocomplete.JQ("#" + spxautocomplete.autoSuggestionsList).text("");
                    spxautocomplete.JQ(elem).appendTo("#" + spxautocomplete.autoSuggestionsList);
                    elem = "";

                    if (spxautocomplete.JQ.trim(spxautocomplete.JQ("#" + spxautocomplete.autoSuggestionsList).text()) === "") {
                        spxautocomplete.JQ("#" + spxautocomplete.autoCompleteSuggestionsBox).hide();
                    } else {
                        spxautocomplete.prototype.bindHoverEvent();
                        spxautocomplete.JQ("#" + spxautocomplete.autoCompleteSuggestionsBox).show();
                    }
                }
            } else {
                spxautocomplete.JQ("#" + spxautocomplete.autoCompleteSuggestionsBox).hide();
            }
        } else {
            if (spxautocompleteconfig.DEBUG_MODE == 1)
                spxautocomplete.prototype.errorHandler(data);
        }
    },

    errorHandler: function(errorJSON) {
        alert(errorJSON.error + ": " + errorJSON.error_description + ", ERROR_CODE:" + errorJSON.error_code);
    }
};

function fixQuotes(value) {
    // replace all the single, double quotes:
    var val = value.replace(/\'/g, "#39;");
    val = val.replace(/\"/g, "#34;");
	 return val;
}

function unFixQuotes(value) {
    // replace all the single, double quotes:
    var val = value.replace(/#39;/g, "\'");
    val = val.replace(/#34;/g, "\"");
    return val;
}
