//inspired by cb_indexedsearch_autocomplete

jQuery.suggest = function(input, options) {
	// Create a link to self
	var me = this;
	var thisForm = jQuery(input).parents('form');

	// Create jQuery object for input element
	var $input = jQuery(input).attr("autocomplete", "off");

	// Create jQuery object for loading indicator
	var $loadingIndicator = jQuery(options.loadingIndicator);

	// Apply inputClass if necessary
	if (options.inputClass) $input.addClass(options.inputClass);

	$results = jQuery('<div>', {
		'id': options.resultsId,
		'class': options.resultsClass
	}).
	appendTo('body').hide();

	input.autocompleter = me;
	input.lastSelected = $input.val();

	var timeout = null;
	var prev = "";
	var active = -1;
	var cache = {};
	var keyb = false;

	$input
	.keydown(function(e) {
		switch(e.keyCode) {
			case 38: // up
				e.preventDefault();
				moveSelect(-1);
				break;
			case 40: // down
				e.preventDefault();
				moveSelect(1);
				break;
			case 13: // return
				if (selectCurrent()) {
					e.preventDefault();
				}
				else {
					thisForm.submit();
				}
				break;
			default:
				active = -1;
				if (timeout) clearTimeout(timeout);
				timeout = setTimeout(onChange, options.delay);
				break;
		}
	})
	.blur(function() {
		hideResults();
	});

	function onChange() {
		var v = $input.val();
		if (v == prev) return;
		prev = v;
		if (v.length >= options.minChars) {
			$loadingIndicator.addClass(options.loadingClass);
			requestData(v);
		} else {
			$loadingIndicator.removeClass(options.loadingClass);
			//$results.hide();
		}
	};

 	function moveSelect(step) {
		var allEntries = jQuery('li', $results);
		if(!allEntries) return;

		//find active entry
		var activeEntry = jQuery('li.over:first', $results);
		var index = allEntries.index(activeEntry);

		index += step;

		if (index < 0) {
			index = 0;
		} else if (index >= allEntries.size()) {
			index = allEntries.size() - 1;
		}

		allEntries.removeClass("over");

		jQuery(allEntries[index]).addClass("over");

		// Weird behaviour in IE
		// if (lis[active] && lis[active].scrollIntoView) {
		// 	lis[active].scrollIntoView(false);
		// }

	};

	function selectCurrent() {
		var li = jQuery("li.over", $results)[0];
		if (!li) {
			var $li = jQuery("li", $results);
			if (options.selectOnly) {
				if ($li.length == 1) li = $li[0];
			} else if (options.selectFirst) {
				li = $li[0];
			}
		}
		if (li) {
			//get url of item
			var url = jQuery('a:first', li).attr('href');
			document.location.href =  url;
			return true;
		} else {
			return false;
		}
	};

	function hideResults() {
		if (timeout) clearTimeout(timeout);
		timeout = setTimeout(hideResultsNow, options.delay);
	};

	function hideResultsNow() {
		if (timeout) clearTimeout(timeout);
		$loadingIndicator.removeClass(options.loadingClass);
		if ($results.is(":visible")) {
			$results.hide();
			if(typeof jQuery.op_header.unswitchFrom == 'function') {
				jQuery.op_header.unswitchFrom('search');
			}
		}
	};

	function receiveData(q, data) {
		if (data) {
			//$loadingIndicator.removeClass(options.loadingClass, 5000);
			setTimeout(function(){
				$loadingIndicator.removeClass(options.loadingClass);
			}, 1000);
			$results.empty();
			//probably not needed, if we do not have pulldowns here
			//if (jQuery.browser.msie) {
			//	// we put a styled iframe behind the calendar so HTML SELECT elements don't show through
			//	$results.append(document.createElement('iframe'));
			//}
			$ul = jQuery('<ul>').appendTo($results);
			jQuery(data).each(function(i){
				if(i >= options.maxResults) return;
				var suggestText = this.search_text;
				var url = (this.turl ? this.turl : this.url);
				var li = jQuery('<li>').appendTo($ul);
				li.hover(
					function() {
						jQuery(this).addClass('over')
					},
					function() {
						jQuery(this).removeClass('over')
					}
				);
				var a = jQuery('<a>', {'html': suggestText, 'href': url}).appendTo(li);
			});
			//add submit button
			//var showAll = jQuery('<a>', {
			//	'text': options.searchAllLabel,
			//	'class': options.submitLinkClass
			//	}).
			//	appendTo($results);
			//jQuery(showAll).click(function(){
			//	thisForm.submit()
			//});

			// TODO: plugin für header classes (active)
			$results.show();
			if(typeof jQuery.op_header.switchTo == 'function') {
				jQuery.op_header.switchTo('search');
			}
		} else {
			removeResults();
			hideResultsNow();
		}
		//add submit button
		var showAll = jQuery('<a>', {
			'html': '<span>'+options.searchAllLabel+'</span>',
			'class': options.submitLinkClass
			}).
			appendTo($results);
		jQuery(showAll).click(function(){
			thisForm.submit()
		});
	};

	function requestData(q) {
		if (!options.matchCase) q = q.toLowerCase();
		var data = options.cacheLength ? loadFromCache(q) : null;
		if (data) {
			receiveData(q, data);
		} else {
			data = findRecords(q);
			if(data && data.length > 0) {
				addToCache(q, data);
				receiveData(q, data);
			}
			else {
				removeResults();
			}
		}
	};

	function removeResults() {
		$loadingIndicator.removeClass(options.loadingClass);
		jQuery('ul', $results).remove();
	}

	function findRecords(q) {
		var results = [];
		//analyze every record
		op_menu.forEach(function(f){
			var score;

			score = f.nav_title.toLowerCase().indexOf(q);
			//not foundin nav_title, try title
			if(score == -1){
				score = weightScore(f.title.toLowerCase().indexOf(q), 100);
				//add weight to the result
			}
			//not found in nav_title and title, search_text
			if(score == -1){
				score = weightScore(strip_tags(f.search_text.toLowerCase()).indexOf(q), 1000);
			}

			if(score > -1) {
				f.score = score;
				results.push(f);
			}
		});
		results.sort(resultSort);
		return results;
	}

	function resultSort(a, b) {
		return a.score - b.score;
	}
	//the higher the modifier, the less important the record is
	function weightScore(weight, modifier) {
		if (weight > -1) {
			return (weight + modifier);
		}
		return -1;
	}

	function makeUrl(q) {
		var url = options.url + "&sw=" + q;
		for (var i in options.extraParams) {
			url += "&" + i + "=" + options.extraParams[i];
		}
		return url;
	};

	function loadFromCache(q) {
		if (!q) return null;
		if (cache[q]) return cache[q];
		//nothing found, must request from server
		return null;
	};

	this.flushCache = function() {
		cache = {};
	};

	this.setExtraParams = function(p) {
		options.extraParams = p;
	};

	function addToCache(q, data) {
		if (!data || !q || !options.cacheLength) return;
		if (!cache.length || cache.length > options.cacheLength) {
			cache = {};
			cache.length = 1; // we know we're adding something
		} else if (!cache[q]) {
			cache.length++;
		}
		cache[q] = data;
	};

}

jQuery.fn.pagesuggest = function(url, options) {
	// Make sure options exists
	options = options || {};
	// Set url as option
	options.url = url;
	// Set default values for required options
	options.inputClass = options.inputClass || "ac_input";
	options.resultsClass = options.resultsClass || "ac_results";
	options.submitLinkClass = options.submitLinkClass || "showAllResults";
	options.resultsId = options.resultsId || "ajaxSearchCall";
	options.minChars = options.minChars || 1;
	options.maxResults = options.maxResults || 6;
	options.delay = options.delay || 400;
	options.matchCase = options.matchCase || 0;
	options.cacheLength = options.cacheLength || 1;
	options.extraParams = options.extraParams || {};
	options.loadingClass = options.loadingClass || "loading";
	options.selectFirst = options.selectFirst || false;
	options.selectOnly = options.selectOnly || false;
	options.searchAllLabel = options.searchAllLabel || false;
	options.loadingIndicator = options.loadingIndicator || "#searchSubmit";

	this.each(function() {
		var input = this;
		new jQuery.suggest(input, options);
	});

	// Don't break the chain
	return this;
}

jQuery(document).ready(function() {
	jQuery("#searchword").
		pagesuggest(op_menu,{minChars:3, cacheLength:20, selectOnly:1, maxResults: 6, searchAllLabel: jsLabels.searchShowAll});
});
