/**
 * Sucheingabe
 */
searchinput = function() {
	this.min				= 2;
	this.last				= null;
	this._last				= null;
	this.auto				= 50;
	this.current			= -1;
	this.count				= 0;
	this.cache				= new Hash();
	this.wrapper			= this.up();
	this.results			= this.wrapper.appendChild(new Element('div', {'class':'search-input-results', 'id': 'productsearch-results'})).hide();
	this.results.fading		= false;
	
	this.onfocus			= this.focus;
	this.onblur				= this.blur.bindAsEventListener(this);
	this.onkeydown			= this.keyDown.bindAsEventListener(this);
	this.onkeyup			= this.keyUp.bindAsEventListener(this);
}

/**
 * Fokusieren des Eingabefeldes
 * 
 * @param {Event} e				Event-Objekt
 */
searchinput.prototype.focus = function(e) {
	if (this.title && this.title.length && (this.title == this.value)) {
		this.value = '';
	}
}

/**
 * Fokusieren des Eingabefeldes
 * 
 * @param {Event} e				Event-Objekt
 */
searchinput.prototype.blur = function(e) {
	if (this._keepFocus) {
		this._keepFocus	= false;
		delete this._keepFocus;
	} else {
		this.collapse();
	}
	if (this.title && this.title.length && !this.value.strip().length) {
		this.value		= this.title;
	}
};

/**
 * OnKeyDown-Handler
 * 
 * @param {Event} e				Event-Objekt
 * @return {Boolean}			Erfolg
 */
searchinput.prototype.keyDown = function(e) {
	Event.extend(e);
	switch (e.keyCode) {
		
		// Enter-Taste wurde gedrückt: Start der Suche
		case Event.KEY_RETURN:
			if (this.results.visible() && (this.current >= 0)) {
				this.selectOption(false, this.current);
			} else {
				this.clearAutoSearch();
				this.collapse();
				this.form.submit();
			}
			Event.stop(e);
			return false;
			break;
		
		// Pfeiltaste nach unten wurde gedrückt
		case Event.KEY_DOWN:
			if (!this.results.visible()) {
				this.search(this.value.strip());
			} else if (this.count && (this.current < this.count - 1)) {
				this.activateOption(this.current + 1);
			}
			return false;
			break;
		
		// Pfeiltaste nach oben wurde gedrückt
		case Event.KEY_UP:
			if (this.results.visible() && this.count && (this.current > 0)) {
				this.activateOption(this.current - 1);
			}
			return false;
			break;
			
		// Escape-Taste wurde gedrückt
		case Event.KEY_ESC:
			this.clearAutoSearch();
			this.collapse();
			break;
			
		// Standard: Tastenanschlag ist zulässig und wird weitergereicht
		default:
			
			break;
	}
}

/**
 * OnKeyUp-Handler
 * 
 * @param {Event} e				Event-Objekt
 * @return {Boolean}			Erfolg
 */
searchinput.prototype.keyUp = function(e) {
	Event.extend(e);
	if (![Event.KEY_RETURN, Event.KEY_DOWN, Event.KEY_UP, Event.KEY_ESC].include(e.keyCode)) {
		var cache		= this.normalize(this.value);
		
		// Wenn ein zwischengespeichertes Ergebnis zum aktuellen Suchbegriff vorliegt: Anzeigen
		if (this.cache.get(cache)) {
			this.clearAutoSearch();
			this.display(cache);
		} else {
			if (this.results.visible() && !this.results.fading && (cache !== this._last)) {
				this.collapse();
			}
			this.initAutoSearch(this.value.strip());
		}
	}
}

/**
 * Initiieren des Timers für die automatische Suche
 * 
 * @param {String} value			Suchbegriff
 */
searchinput.prototype.initAutoSearch = function(value) {
	if ((this.auto > 0) && (value.length >= this.min)) {
		this.clearAutoSearch();
		this.autoSearchTimer	= window.setTimeout(this.search.bind(this, value), this.auto);
	}
}

/**
 * Löschen des Timers für die automatische Suche
 */
searchinput.prototype.clearAutoSearch = function() {
	if ((this.auto > 0) && (this.autoSearchTimer !== null)) {
		window.clearTimeout(this.autoSearchTimer);
		this.autoSearchTimer = null;
	}
}

/**
 * Suchvorgang
 * 
 * @param {String} value			Suchbegriff
 */
searchinput.prototype.search		= function(value) {
	this.clearAutoSearch();
		
	// Wenn nicht zuletzt nach diesem Wert gesucht wurde: Neue Suche
	if (value !== this.last) {
		if (value.length >= this.min) {
			this.call(value);
		}
		
	// Ansonsten: Erneutes Anzeigen der vorherigen Suchergebnisse
	} else {
		this.appearResults();
	}
}

/**
 * Durchführen einer AJAX-Suche
 * 
 * @param {String} value		Suchbegriff(e)
 * @param {Object} params		Zusätzliche Parameter
 */
searchinput.prototype.call = function(value, params) {
	this.addClassName('searching');
	this.last 				= value;
	this._last				= this.normalize(value);
	this.options			= [];
	new Ajax.Request('/', {method: 'get', parameters: {'type': 902, 'tx_fleshop_searchresults[action]': 'quicksearch', 'tx_fleshop_searchresults[controller]': 'Search', 'tx_fleshop_searchresults[swords]': this._last}, onComplete: this.receive.bind(this)});
}

/**
 * Normalisieren eines Suchbegriffs
 * 
 * @param {String} value		Suchwert
 * @return {String}				Normalisierter Suchwert
 */
searchinput.prototype.normalize = function(value) {
	value					= value.toLowerCase().split(' ');
	var terms				= [];
	for (var v = 0; v < value.length; ++v) {
		var term			= value[v].strip();
		if (term.length) {
			terms.push(term);
		}
	}
	terms.sort();
	return encodeURIComponent(terms.join(' '));
}

/**
 * Ergebnis-Callback nach AJAX-Suche
 * 
 * @param {Object} response		AJAX-Antwort
 */
searchinput.prototype.receive	= function(response) {
	this.removeClassName('searching');
	var cache			= response.getHeader('X-Search-Terms').strip();
	
	// Zwischenspeichern des Ergebnisses
	if (cache.length) {
		this.cache.set(cache, response.responseText);
	}

	// Wenn das Suchergebnis auf die zuletzt gesendete Anfrage zutrifft: Anzeigen
	if (cache == this._last) {
		this.display(cache);
	}
}

/**
 * Anzeigen eines Suchergebnisses
 * 
 * @param {String} cache			Zwischenspeicherschlüssel
 */
searchinput.prototype.display = function(cache) {
	this.results.update(this.cache.get(cache));
	this.options		= this.results.select('a');
	for (var option = 0; option < this.options.length; ++option) {
		this.options[option].observe('mouseover', this.activateOption.bind(this, option));
		this.options[option].observe('mousedown', this.selectOption.bindAsEventListener(this, option));
		this.options[option].onclick = function(e) { Event.stop(e); return false; };
	}
	this.current		= -1;
	this.count			= this.options.length;
	this.appearResults();
}

/**
 * Aktivieren einer Ergebnisoption
 * 
 * @param {Number} option		Optionsindex
 */
searchinput.prototype.activateOption = function(option) {
	if (this.current >= 0) {
		this.options[this.current].removeClassName('active');
	}
	this.current = option;
	this.options[this.current].addClassName('active');
}

/**
 * Auswählen einer Ergebnisoption
 * 
 * @param {Event} e				Event-Objekt
 * @param {Node} option			Option
 * @return {Boolean}			Erfolg
 */
searchinput.prototype.selectOption = function(e, option) {
	this.collapse();
	document.location.href = this.options[option].href;
	if (e) {
		Event.stop(e);
	}
	return false;
}

/**
 * Einblenden der Suchergebnisse
 */
searchinput.prototype.appearResults = function() {
	
	// Ausblenden der Ergebnisseite beim Verlassen der Combo-Box oder der Ergebnisanzeige
	document.onmousedown	= this.fadeResults.bindAsEventListener(this);
	this.results.fading		= true;
	Effect.Appear(this.results, {'duration': 0.2, 'afterFinish': function() { this.fading = false; }.bind(this.results) });
}

/**
 * Ausblenden der Suchergebnisse
 * 
 * @param {Event} e				Event-Objekt
 */
searchinput.prototype.fadeResults = function(e) {
	if (!Event.element(e).descendantOf(this.wrapper)) {
		document.onmousedown = null;
		this.collapse();
	} else {
		this._keepFocus = true;
	}
}

/**
 * Ausblenden der Combo-Ergebnisse
 */
searchinput.prototype.collapse = function() {
	this.results.fading = true;
	Effect.Fade(this.results, {'duration': 0.2, 'afterFinish': function() { this.fading = false; }.bind(this.results) });
	if (this.current >= 0) {
		this.options[this.current].removeClassName('active');
	}
	this.current	= -1;
}

// Initialisierung beim vollständigen Laden der Seite
document.observe("dom:loaded", function() {
	var productSearch = $('quicksearchfield');
	if(productSearch){
		Object.extend(productSearch, searchinput.prototype);
		searchinput.apply(productSearch);
	}
});
