/*
	
	If you have multple selectable search options, use the method setSearchOptionMultiple;
			
	The structure of your DOM should resemble this:
	
		<ul searchoption="myOption">
			<li searchoptionvalue="1">One</li>
			<li searchoptionvalue="2" class="selected">Two</li>
		</ul>
	
	It is not important to use <ul>, but you must use a parent-child-structure of search option and search option value.
	
	Requires jQuery bind Plugin (http://plugins.jquery.com/project/bind)
	
*/

// Reverse method for jQuery
$.fn.reverse = [].reverse;

whitewall.SearchController = function() {
	
	return {
	
		FORM: $("#searchForm"),
	
		init: function() {
			$.bind(this, this.reset);
			$.bind(this, this.setSearchOption);
			$.bind(this, this.setSearchOptionMultiple);
			$.bind(this, this.addSearchCategory);
			$.bind(this, this.removeSearchCategory);
			$.bind(this, this.readSortSelection);
		},
	
		setSearchOption: function(event) {
			var element = $(event.target);
			if (element.parents("#category_selector").size() > 0) {
			  // Do nothing if a category was clicked
			  // This behaviour is set in market_search.js
			}	else {
				var searchOption = this.getSearchOption(element);
				if (searchOption.multiple) {
					this._searchOptionMultiple(element);
				} else {
					this._setSearchField(searchOption.field, searchOption.value);
				}
			}
		},
		
		/*
			This method is used to set a field value for multi-value fields.
			
			You can either pass a HTML-element or an event (a jQuery.Event does also work).
			
			@return		an object containing the search option and the new field value as an array
		*/
		setSearchOptionMultiple: function(element) {		
			// Get all selected search option values
			var selectedElements = element.parents("[searchoption]").find(".selected");
			var selectedArray = [];
			selectedElements.each(function(index) {
				selectedArray.push($(this).attr("searchoptionvalue"));
			});
			// Write all values to field
			var searchOption = this.getSearchOption(element);
			this._setSearchField(searchOption.field, selectedArray.toString());
		},
		
		setSearchOptionDirect: function(option, value) {
			var field = this.getSearchOptionField(option);
			this._setSearchField(field, value);
		},
		
		/*
			Internal method. Just set's a fields value, but allows any pre-processing (like logging)
		*/
		_setSearchField: function(field, value) {
			if (field === undefined) {
				if (console !== undefined) {
          console.error("Undefined field!");
        }
			}
			if (value == null || value == "null") {
				value = "";
			}
			if (console !== undefined) {
        console.log("Setting field: '" + field.attr("name") + "' with value '" + value + "'");
      }
			field.val(value);
		},
	
		/*
			Returns the corresponding form field to a search option
		*/
		getSearchOptionField: function(option) {
			return this.FORM.children("[name=" + option + "]");
		},
	
		/*
			Returns a searchOption object, based on a DOM element, with these fields:
			
			 - the search options name
			 - the search options value
			 - the corresponding form field (jQuery object)
			 – a bollean if the search option is multi-valued
		*/
		getSearchOption: function(element) {
			var value = element.attr("searchoptionvalue");
			var option = element.parents("[searchOption]").attr("searchoption");
			var field = this.FORM.children("[name=" + option + "]");
			if (field.size() < 1) {
				if (console != undefined) console.error("Could not find field for search option '" + "'");
			}
			// As we are in the columnnav, we either get a <li><a>Text</a></li> or just and <li>
			var text;
      if (element.children().size() > 0) {
				text = element.find("> a").text();
			} else {
				// Leaf node
				text = element.text();
			}
			var isMultiple = element.parents("[searchOption]").attr("searchoptionmultiple") == true;
			return { 'option': option, 'value': value, 'field': field, 'text': text, "multiple": isMultiple };
		},
	
		// ========================================
		// = Methods for search category handling =
		// ========================================
		
		addSearchCategory: function(element) {
			this.setSearchOptionMultiple(element);
		
			// Part 1: Update the form field
			var searchOption = this.getSearchOption(element);
			
			// Part 2: Update the UI
			var categoryParent = element.parents("[searchoptionvalue]").get(0);
			var nodeMarkup = "<li class='selected selectable-list-selected' searchoptionvalue='" + searchOption.value + "'>" + searchOption.text + "</li>";
			$("#selected_categories").show();
			$("#selected_categories").parent().show();
			if (categoryParent) {
				// This is a subcategory: append it to its parent
				var parent = $("#selected_categories [searchoptionvalue=" + $(categoryParent).attr("searchoptionvalue") + "]");
				if (parent.size() < 1) {
				  // The parents are not yet added to the selected categories. Add them now
				  var parents = element.parents("[searchoptionvalue]").reverse();
				  // Make sure they all have the selected class
				  // XXX Bad style: connects visual with logic, but currently no other way :(
				  parents.addClass("selectable-list-selected").addClass("selected");
				  var searchController = this;
				  parents.each(function() {
				    var elem = $(this);
				    // Add the element (if it is not yet in the selected categories)
				    if ($("#selected_categories [searchoptionvalue=" + elem.attr("searchoptionvalue") + "]").size() == 0) {
				      searchController.addSearchCategory(elem);
				    }
				  });
				  // Re-evaluate parents (they now should exist)
				  parent = $("#selected_categories [searchoptionvalue=" + $(categoryParent).attr("searchoptionvalue") + "]");
				}
				// If there is not yet a list for the category childs, create one
				if (parent.children("ul").size() < 1) {
					 parent.append("<ul></ul>");
				}
				parent.children("ul").append(nodeMarkup);
			} else {
				// This is a root category
				$("#selected_categories").append(nodeMarkup);
			}
		},
	
		/*
			Removes a category and any of it's child categories from the search form input field.
		
			@param	element		The DOM element of the (clicked) parentCategory
			@param	parentCategory	The name of the parentCategory (a string)
			@param	field		The input field that containing all categories
		*/
		removeSearchCategory: function(element) {
			this.setSearchOptionMultiple(element);
			
			var searchOption = this.getSearchOption(element);
			
			// Part 2: Update the UI: Remove corrensponding node from selected categories tree
			$("#selected_categories [searchoptionvalue=" + $(element).attr("searchoptionvalue") + "]").remove();
		},
	
		/*
			Updates ONLY the UI to represent no selected categories. The logic part (i.e. clearing the form field)
			is already done via whitewall.SearchController.resetSearchOptions().
		*/
		removeAllSearchCategories: function() {
			// Unselect all list elements
			$("#category_column_navigation .selected").removeClass("selected").removeClass("selectable-list-selected");
			// Empty the selected categories tree
			$("#selected_categories").empty();
			this.setSearchOptionDirect("categories", "");
		},
		
		// Sets the dropdown to the value of the field
		readSortSelection: function() {
		    var searchOption = $("#sortSelect").attr("searchoption");
				var value = this.getSearchOptionField(searchOption).val();
				$("#sortSelect").selectOptions(value);	// jQuery selectBoxes Plugin
		},
		
		// Sets the field to the value of the dropdown
		setSortSelection: function() {
			var searchOption = $("#sortSelect").attr("searchoption");
	    var selected = $("#sortSelect").selectedValues();
	    this.setSearchOptionDirect(searchOption, selected);
		},
		
		reset: function() {
			// Reset the form
			this.FORM.get(0).reset();
				
			// Reset UI elements
			this.removeAllSearchCategories();
			// Clear input fields
			$("#sidebar_menu input").attr('value', '');
			// Reset elements that have a searchoptionvalue attribute
			$("[searchoptionvalue]").removeClass("selectable-list-selected");
			// Reset the default options (like "Time: All")
			$("[searchoptiondefault='true']").click();
		},

		submit: function() {
			/*
			
				Submitting the form is done in market_AjaxHandler.js!
			
			*/
			return false;
		},


    translateFulltext: function(timerHandle, deferredHandler) {
      var text = $("#searchQuery").attr("value");

      if (text && text.length > 0)
      {
        google.language.detect(text, function(result)
        {
          if (!result.error && result.language)
          {
            var lang = result.language;
            // we now have most times an english translation
            google.language.translate(text, result.language, "en", function(result) {
              if (timerHandle[0] !== null)
              {
                // if not english and translation available
                if (lang != "en" && result.translation) {
                    $("#queryTranslation").attr("value", result.translation);
                } else {
                    $("#queryTranslation").attr("value", "");
                }
                if (console) {
                  console.log("Detected: '"+text+"' as '"+lang+"' and translated to: '"+result.translation+"'");
                }

                window.clearTimeout(timerHandle[0]);
                deferredHandler();
              }
            }); // end inner inner closure
            }
        }); // end inner closure
      } else {
        $("#queryTranslation").attr("value", "");
      }

    }
	};

	
};