/*
 * All java script logic for the search suggestions.
 *
 * The code relies on the jQuery JS library to
 * be also loaded.
 *
 * The logic extends the JS namespace app.*
 * 
 * Can be instantiated more than once
 * 
 */
(function (app) {
	if (app) {
		// add searchsuggest to namespace
		app.searchsuggest = {
			//be backward compatible
			init : function(formId, fieldId, fieldDefault, resultsId, url, resultsDivWidth) {
				 return new app.searchsuggest.SuggestionHandler().initialize(formId, fieldId, fieldDefault, resultsId, url, resultsDivWidth);
			},
		
			SuggestionHandler: function () {
				this.acListTotal = 0;
				this.acListCurrent = -1;
				this.acDelay = 300;
				this.acURL = null;
				this.acFormId = null;
				this.acSearchId = null;
				this.acResultsId = null;
				this.acSearchField = null;
				this.acResultsDiv = null;
				this.fieldDefault = null;
				this.acResultsDivWidth = null;
				this.showdbg = false; // enables console debug info 
				var _self = this; // this reference
						
				this.initialize = function (formId, fieldId, fieldDefault, resultsId, url, resultsDivWidth) {
					window.console && this.showdbg && console.log('app.searchsuggest.init');
					// initialize vars
					this.acFormId = "#" + formId;
					this.acSearchId = "#" + fieldId;
					this.acResultsId = "#" + resultsId;
					this.acURL = url;
					this.fieldDefault = fieldDefault;
					resultsDivWidth != null ? this.acResultsDivWidth = resultsDivWidth : this.acResultsDivWidth = null;

					// disable browser auto comlete
					app.util.disableAutoComplete(fieldId);

					// create the results div
					jQuery("body").append("<div id=\"" + resultsId + "\"></div>");

					// register mostly used vars (jQuery object)
					this.acSearchField = jQuery(this.acSearchId);
					this.acResultsDiv = jQuery(this.acResultsId);

					// reposition div
					this.repositionResultsDiv();
					
					// on blur listener
					this.acSearchField.bind("blur", this, function(e){
						setTimeout(e.data.clear,250);
					});
					
					// on key up listener
					this.acSearchField.keyup(function (e) {
						// get keyCode (window.event is for IE)
						var keyCode = e.keyCode || window.event.keyCode;
						var lastVal = _self.acSearchField.val();
						// check an treat up and down arrows
						if (_self.updownArrow(keyCode)) {
							return;
						}
						// check for an ENTER or ESC
						if (keyCode == 13 || keyCode == 27) {
							_self.clear();
							return;
						}

						// if is text, call with delay
						setTimeout(function () {
							_self.suggest(lastVal)
						}, _self.acDelay);
					});

					// on focus listener (clear default value)
					this.acSearchField.focus(function () {
						var val = _self.acSearchField.val();
						if (val == _self.fieldDefault) {
							_self.acSearchField.val("");
						}
					});

					// on submit we do not submit the form, but change the window location
					// in order to avoid https to http warnings in the browser
					jQuery(this.acFormId).submit(function () {
						var searchUrl = jQuery(_self.acFormId).attr("action");
						var searchTerm = _self.acSearchField.val();
						window.location = app.util.appendParamToURL(searchUrl, "q", searchTerm);
						return false;
					});
				};


				// trigger suggest action
				this.suggest = function (lastValue) {
					window.console && this.showdbg && console.log('this.suggest');
					// get the field value
					var part = this.acSearchField.val();

					// if it's empty clear the resuts box and return
					if (part == "") {
						this.clear();
						return;
					}

					// if it's equal the value from the time of the call, allow
					if (lastValue != part) {
						return;
					}

					// build the request url
					var reqUrl = app.util.appendParamToURL(this.acURL, "q", part);

					// get remote data as JSON
					jQuery.getJSON(reqUrl, function (json) {
						// get the total of results
						var ansLength = _self.acListTotal = json.suggestions.length;

						// if there are results populate the results div
						if (ansLength > 0) {

							var newData = "";
							// create a div for each result
							for (i = 0; i < ansLength; i++) {
								newData += "<div class=\"unselected\"><div class=\"suggestionterm\">" + json.suggestions[i].suggestion + "</div>";
								newData += "<span class=\"hits\">" + json.suggestions[i].hits + "</span></div>";
							}
							// update the results div
							_self.acResultsDiv.html(newData);
							_self.acResultsDiv.css("display", "block");
							// reposition in case user resizes browser between searches
							_self.repositionResultsDiv();

							// for all divs in results
							var divs = jQuery(_self.acResultsId + " > div");
							window.console && this.showdbg && console.log('divs ' + divs);

							// on mouse over clean previous selected and set a new one
							divs.mouseover(function () {
								divs.each(function () {
									this.className = "unselected";
								});
								this.className = "selected";
							});

							// on click copy suggestion to search field, hide the list and submit the search
							divs.click(function () {
								_self.acSearchField.val(jQuery(this).children().first().text());
								_self.clear();
								jQuery(_self.acFormId).submit();
							});
						} else {
							_self.clear();
						}
					});
				};

				// clear suggestions
				this.clear = function () {
					window.console && _self.showdbg && console.log('this.clear');
					_self.acResultsDiv.html("");
					_self.acResultsDiv.css("display", "none");
				};

				// reposition the results div accordingly to the search field
				this.repositionResultsDiv = function () {
					window.console && this.showdbg && console.log('this.repositionResultsDiv');
					// get the input position
					var inPos = this.acSearchField.offset();
					window.console && this.showdbg && console.log('inPos.top =  ' + inPos.top + '   inPos.left = ' + inPos.left);
					var inTop = inPos.top;
					var inLeft = inPos.left;

					// get the field size
					var inHeight = this.acSearchField.outerHeight();
					var inWidth = this.acSearchField.outerWidth();
					window.console && this.showdbg && console.log('inHeight  =  ' + inHeight);
					// apply the css styles
					this.acResultsDiv.addClass("suggestions");
					this.acResultsDiv.css("position", "absolute");
					this.acResultsDiv.css("left", inLeft + 'px'); // to tweak
					this.acResultsDiv.css("top", inTop + inHeight + 1);
					this.acResultsDiv.css("width", this.acResultsDivWidth != null ? this.acResultsDivWidth : inWidth);
					this.acResultsDiv.css("z-index", "7777");
				};

				// treat up and down key strokes defining the next selected element
				this.updownArrow = function (keyCode) {
					if (keyCode == 40 || keyCode == 38) {
						if (keyCode == 38) { // keyUp
							if (_self.acListCurrent == 0 || _self.acListCurrent == -1) {
								_self.acListCurrent = _self.acListTotal - 1;
							} else {
								_self.acListCurrent--;
							}
						} else { // keyDown
							if (_self.acListCurrent == _self.acListTotal - 1) {
								_self.acListCurrent = 0;
							} else {
								_self.acListCurrent++;
							}
						}

						// loop through each result div applying the correct style
						this.acResultsDiv.children().each(function (i) {
							if (i == _self.acListCurrent) {
								_self.acSearchField.val(jQuery(this).children().first().text());
								this.className = "selected";
							} else {
								this.className = "unselected";
							}
						});
						return true;
					} else {
						// reset
						_self.acListCurrent = -1;
						return false;
					}
				};
			}
		};
	} else {
		// namespace has not been defined yet
		alert("app namespace is not loaded yet!");
	}
})(app);
