/**
 * Globaler Namesnraum für die Suche anlegen.
 * 
 * @author marlettas
 * 		$LastChangedBy: marlettas $
 * 		$LastChangedDate: 2010-07-29 14:40:03 +0200 (Thu, 29 Jul 2010) $
 * 
 * @version $Id: Search.js 14555 2010-07-29 12:40:03Z marlettas $ 
 */
var Search = {};

/**
 * Blend Effekt für alle Searchgadgets
 */
Search.Gadget = Class.create({
	eventName: false,
	element: false,
	initialize: function(parameters) {
		if(!parameters || !parameters.element)
			throw new Error("Search.Gadget needs an element to use.");
			
		this.element = parameters.element;
		
		this.eventName = this.element.readAttribute("eventName");
		document.observe(this.eventName, function() {
			this.element.select(".refineSearchHeadline").invoke("removeClassName", "loading");
		}.bind(this));
	},
	fadeOut: function() {
		this.element.select(".refineSearchHeadline").invoke("addClassName", "loading");
		this.element.select(".multiValueChooser").invoke("addClassName", "disabled");
	}
});

/**
 * Klasse für den Treffer-Zähler.
 */
Search.HitCount = Class.create({
	element: false,
	lastSearch: false,
	parser: false,
	mode: "",
	
	/** @lends Search.HitCount */
	/**
	 * Leider kann bei parameters.element keine Exception ausgelöst werden, da der IE dies nicht 
	 * unterstützt.
	 */
	initialize: function(parameters) {
		if(parameters && parameters.mode) {
			this.mode = parameters.mode;
		}
		
		if(parameters && parameters.element) {
			this.element = parameters.element;
		
			this.element.select("[name]").each(function(namedInput) {
				var searchOn = namedInput.readAttribute("searchOn");
				if(searchOn && searchOn.length > 1){
					namedInput.observe(
							searchOn,
						this.onSearch.bind(this)
					);
				}
			}.bind(this));
			
			Platform.Registry.register("hitCount", this);
		}
		
		this.setupForm();
	},
	onSearch: function(updateEvent) {
		if(updateEvent && updateEvent.findElement().hasClassName("disabled"))
			return;
		
		if($("searchGadget")) {
			var searchGadget = new Search.Gadget({
				element: $("searchGadget")
			});
			searchGadget.fadeOut();	
		}
		
		
		var url = "";
		var ranges = {};
		
		var lastCategory = "";
		var parenthesis = false;
		
		this.element.select("[name]").each(function(namedInput) {
			try {
				var value = $F(namedInput) ? $F(namedInput) : namedInput.readAttribute("value");
				var logicalOperator = namedInput.readAttribute("operator") ? namedInput.readAttribute("operator") : "";
				if(
					namedInput.readAttribute("name") != "q" && 
					namedInput.readAttribute("name") != "content" &&
					namedInput.readAttribute("name") != "page" &&
					value && 
					value != "Alle" && 
					value != "bitte wählen" 
				) {
					var urlAppend = true;
					var elementName = namedInput.readAttribute("name");
					
					if(namedInput.hasClassName("from")) {
						if(!ranges[elementName])
							ranges[elementName] = new Search.Range(elementName);
						
						ranges[elementName].from = value;
						
						urlAppend = false;
					} else if(namedInput.hasClassName("to")) {
						if(!ranges[elementName])
							ranges[elementName] = new Search.Range(elementName);
						
						ranges[elementName].to = value;
						
						urlAppend = false;
					}
					
					try {
						if(urlAppend && $F(namedInput)) {
							// console.log("1. last: %o || new: %o", lastCategory, namedInput.readAttribute("category"));
							if($F(namedInput) != "*") {
								if(
									url != ""  && 
									lastCategory == namedInput.readAttribute("category")
								)
									url += " " + logicalOperator;
								else if(
									url != "" && 
									lastCategory != namedInput.readAttribute("category")
								) {
									if(parenthesis) {
										url += ")";
										parenthesis = false;
									}
									
									url += " AND";
									
									if(!parenthesis) {
										url += " (";
										parenthesis = true;
									}
								}
								
								// console.log("El: %o || Value: %o", namedInput.readAttribute("name"), $F(namedInput));
								
								url += " " + namedInput.readAttribute("name") + ":" + $F(namedInput);
								lastCategory = namedInput.readAttribute("category");
							}
						}else if(urlAppend && namedInput.hasClassName("selected")) {
							// console.log("2. last: %o || new: %o", lastCategory, namedInput.readAttribute("category"));
							if(namedInput.readAttribute("value") != "*") {
								if(
									url != "" && 
									lastCategory == namedInput.readAttribute("category")
								)
									url += " " + logicalOperator;
								else if(
									url != "" && 
									lastCategory != namedInput.readAttribute("category")
								) {
									if(parenthesis) {
										url += ")";
										parenthesis = false;
									}
									
									url += " AND";
									
									if(!parenthesis) {
										url += " (";
										parenthesis = true;
									}
								}
								
								url += " " + namedInput.readAttribute("name") + ":" + 
									namedInput.readAttribute("value");
								// console.log("El: %o || Value: %o", namedInput.readAttribute("name"), namedInput.readAttribute("value"));
								lastCategory = namedInput.readAttribute("category");
							}
						}
					}catch(exc) {
						console.error(exc);
					}
				}
					
			}catch(exception) {
				if(namedInput.hasClassName("selected")) {
					// console.log("3. last: %o || new: %o", lastCategory, namedInput.readAttribute("category"));
					var value = namedInput.readAttribute("value");
					var logicalOperator = namedInput.readAttribute("operator") ? namedInput.readAttribute("operator") : "";

					if(value != "*") {
						if(url != "" && lastCategory == namedInput.readAttribute("category"))
							url += " " + logicalOperator;
						else if(url != "" && lastCategory != namedInput.readAttribute("category")) {
							if(parenthesis) {
								url += ")";
								parenthesis = false;
							}
							
							url += " AND";
							
							if(!parenthesis) {
								url += " (";
								parenthesis = true;
							}
						}
						
						url += " " + namedInput.readAttribute("name") + ":" + value;
						// console.log("El: %o || Value: %o", namedInput.readAttribute("name"), value);
						lastCategory = namedInput.readAttribute("category");
					}
				}
			}
		});

		try {
			Object.keys(ranges).each(function(rangeKey) {
				if(ranges[rangeKey].from != "*" || ranges[rangeKey].to != "*") {
					url += [
					        " ", ranges[rangeKey].field, ":[", ranges[rangeKey].from, " TO ", 
					        ranges[rangeKey].to, "]"
					].join("");
				}
			});
		}catch(e) {
			console.error("E: %o", e);
		}
		
		if(parenthesis)
			url += ")";
		
		url = url.length > 0 ? url : "*:*"; 
		$("luceneQ").setValue(url);
		
		var params = {
			rows: 0,
			wt: "json",
			q: url
		};

		try {
			new Ajax.Request(this.getServiceUrl(), {
				method: "get",
				parameters: params,
				onComplete: function(transport) {
					this.lastSearch = transport.responseText.evalJSON();
					if(this.mode != "hidden") {
						$("hitCount").update(this.lastSearch.response.numFound);
						document.fire("hitCount:updated");
					}
				}.bind(this)
			});
		}catch(exc) {
			console.error(exc); 
		}
	},
	getServiceUrl: function() {
		return "/search/";
	},
	setupForm: function() {
		this.parser = new Solr.Parser();
		var parserResult = this.parser.parse();

		if(parserResult) {
			parserResult.each(function(fieldParameter) {
				if(fieldParameter.value != "*" && fieldParameter.value !== false) {
					$$("[name=" + fieldParameter.name + "]").each(function(element) {
						try {
							var elementType = element.readAttribute("type");
							if(
								elementType == "checkbox" && 
								element.readAttribute("value") == fieldParameter.value
							) {
								element.writeAttribute({"checked": true});
							}else if(
								elementType == "checkbox" && 
								element.readAttribute("value") != fieldParameter.value
							) {
								if(!element.readAttribute("checked"))
									element.writeAttribute({"checked": false});
							}else {
								element.setValue(fieldParameter.value);
							}
						}catch(exc_outer) {
							try {
								//element.writeAtribute({"value": fieldParameter.value});
								if(element.readAttribute("value") == fieldParameter.value)
									element.addClassName("selected");
							}catch(exc_inner) {
								console.error(exc);
							}finally {
								element.fire("component:change");
							}
						}finally {
							element.fire("component:change");
						}
					});
				}else if(fieldParameter.value == false && (fieldParameter.from || fieldParameter.to)) {
					try {
						$$("[name=" + fieldParameter.name + "]").each(function(element) {
							if(element.hasClassName("from")) {
								element.setValue(fieldParameter.from);
							}else if(element.hasClassName("to")) {
								element.setValue(fieldParameter.to);
							}else {
								var rangeValue = "[" + fieldParameter.from  + " TO " + 
									fieldParameter.to + "]";
								
								if(element.setValue)
									element.setValue(rangeValue);
								else
									element.writeAttribute({ "value": rangeValue });
							}
							
							element.fire("component:change");
						});
					}catch(exception) {
						console.error(exception);
					}
				}
			});
		}

		this.onSearch();
	}
});

Search.componentComplete = function(transport, element) {
	if(Platform.Registry.get("hitCount")) {
		var solrParser = Platform.Registry.get("hitCount").parser;
		
		if(solrParser) {
			element.select("[name]").each(function(namedElement) {
				var parsedQ = solrParser.parse();
				
				if(parsedQ) {
					parsedQ.each(function(parsedField) {
						if(parsedField.name == namedElement.readAttribute("name")) {
							namedElement.setValue(parsedField.value);
							Platform.Registry.get("hitCount").onSearch();
							namedElement.fire("component:change");
						}
					});
				}
			});
		}
	}
}

Search.vendorChooserChanged = function(changeEvent) {
	var option = this.select("option[vendorName=" + $F(this) + "]").first();
	if(!option) {
		option = this.select("option[vendorId=" + $F(this) + "]").first();
	}
	
	var relation = new Platform.Component.Relation({
		requestParameters: {
			vendorId: option ? option.readAttribute("vendorId") : false,
			componentSetup: option ? option.readAttribute("componentSetup") : false
		},
		onComplete: Search.componentComplete
	}); 
	Platform.ComponentLoader.load(
		$(this.readAttribute("rel")), 
		this.readAttribute("component"),
		relation
	);
}

Search.disableCategories = function(strDisableCategories) {
	Search.enable(strDisableCategories, false);
}

Search.enableCategories = function(strEnableCategories) {
	Search.enable(strEnableCategories, true);
}

Search.enable = function(strSelector, isEnabled) {
	if(strSelector) {
		strSelector.split(" ").each(function(selector) {
			var invokeMethod = isEnabled ? "enable" : "disable";
			
			$$("[category=" + selector + "]").invoke(invokeMethod);
		});
	}
}

Search.Range = Class.create({
	from: "*",
	to: "*",
	field: "",
	initialize: function(parameters) {
		this.field = parameters;
	}
});

Search.Facets = Class.create({
	element: false,
	neededfacetQueries: false,
	facetQ: false,
	oldQ: false,
	initialize: function(parameters) {
		if(parameters && parameters.element)
			this.element = parameters.element;
		
		document.observe("hitCount:updated", function(domEvent) {
			this.process();
		}.bind(this));
	},
	process: function() {
		this.oldQ = $("luceneQ").getValue();
		
		if(!this.oldQ || this.oldQ.length <= 0) {
			var parser = new Solr.Parser();	
			this.oldQ = parser.solrQ;
		}
		
		if(!this.oldQ) {
			this.oldQ = "";
			
			$$(".requestFilter").each(function(requestFilter) {
				this.oldQ += requestFilter.readAttribute("name") + ":" + $F(requestFilter) + "+";
			}.bind(this));
		}
		
		this.facetQ = {};
		
		this.facetQ.facet = true;
		this.neededFacetQueries = new Array();
		
		this.element.select("[name]").each(function(facetElement) {
			var elementName = facetElement.readAttribute("name");
			if(!facetElement.hasClassName("selected")) {
				var item = {
					name: elementName,
					value: facetElement.readAttribute("value")
				};
				this.neededFacetQueries.push(item);
			}
		}.bind(this));
		
		this.neededFacetQueries = this.neededFacetQueries.uniq();
		this.neededFacetQueries.each(function(facedQuery) {
			if(!this.facetQ["facet.query"])
				this.facetQ["facet.query"] = new Array();
			
			this.facetQ["facet.query"].push(facedQuery.name + ":" + facedQuery.value);
		}.bind(this));
		
		var params = this.facetQ;
		params.rows = 0;
		params.wt = "json";
		params.q = this.oldQ;
		
		new Ajax.Request("/search/", {
			method: "get", 
			parameters: params,
			onComplete: function(transport) {
				try {
					var facetsResult= transport.responseText.evalJSON();
					this.processFacetQueries(facetsResult.facet_counts.facet_queries);
				}catch(exc) {
					console.error(exc);
				}
			}.bind(this)
		});	
	},
	processFacetQueries: function(facetQueries) {
		this.neededFacetQueries.each(function(neededQuery) {
			this.element.select("[value=" + neededQuery.value + "]").each(function(queryField) {
				if(
					queryField.readAttribute("name") == neededQuery.name &&
					!queryField.hasClassName("selected")
				) {
					var value = facetQueries[neededQuery.name + ":" + neededQuery.value]; 
					queryField.select(".facetCounter").invoke("remove");
					
					if(value <= 0)
						queryField.fire("facet:disable", { 
							name: queryField.readAttribute("name"),
							value: queryField.readAttribute("value")
						});
					else {
						var counterElement = new Element("ins");
						counterElement.addClassName("facetCounter");
						counterElement.update("(" + value + ")");
											
						queryField.insert({ "bottom": counterElement });
						queryField.fire("facet:enable", { 
							name: queryField.readAttribute("name"),
							value: queryField.readAttribute("value")
						});
					}
				}
			});
		}.bind(this));
		
		this.element.select(".multiValueChooser").each(function(filter) {
			if(filter.hasClassName("selected")) {
				filter.fire("facet:enable", { 
					name: filter.readAttribute("name"),
					value: filter.readAttribute("value")
				});
			}				
		});
		document.fire("facets:ready");
	}
});