McCannFancySearch = Class.create({
	/*
		Attempt to use and adjust the normal SiteConponents Search Form.
	
		The constructor checks to see if all requirements are met. If
		something is not ok, then the old search input is left as is,
		working as usual.
	
		If everything is ok, different events are set up to build a fancy
		ajax search based on user input.
		
		Author: Simen Lysebo, July 2010
	*/
	
	searchContainer: null,	// the div encapsulating the search form
	searchInput: null,		// the search input text element
	progressContainer: null,	// the div encapsulating the progress indicator
	resultContainer: null,	// the wrapper for the search result/status info

	currentSearchString: null,	// holds the current search string
	resultIsVisible: null,		// flag determining if the result container is visible
	activeResult: null,			// pointer to the active selected item
	totalResults: null,			// the current number of search results

//TODO selected search hit i msie6---------------------------------------------

	initialize: function() {
		var ok = true;
		
		this.resultIsVisible = false;
		this.currentSearchString = "";
		this.totalResults = 0;
		
		// get hold of search container, progress container and result container
		if ($('placeholder-top') && $('placeholder-top').down('div.small-searchinput')
		&& $('mcCannFancySearch') && $('mcCannFancySearch').down('div.innerWrapper')
		&& $('mcCannFancySearch').down('div.innerWrapper').down('div.progress')
		&& $('mcCannFancySearch').down('div.innerWrapper').down('div.result')) {
			this.searchInput = $('placeholder-top').down('div.small-searchinput').down('input.textinput');
			this.progressContainer = $('mcCannFancySearch').down('div.innerWrapper').down('div.progress');
			this.resultContainer = $('mcCannFancySearch').down('div.innerWrapper').down('div.result');
		} else {
			ok = false;
		}
		
		// only continue if ok
		if (!ok) {
			return;
		}
		
		// disable autocomplete on form input
		this.searchInput.setAttribute("autocomplete", "off");

		// set up blur event handler on search input
		this.searchInput.observe('blur', function(event){
			this.handleBlur();
		}.bindAsEventListener(this));
		
		// set up keyup event handler on search input
		this.searchInput.observe('keyup', function(event){
			event.stop();
			this.handleKeyUp(event);
		}.bindAsEventListener(this));

		// set up keypress event on search input (to trigger enter)
		this.searchInput.observe('keypress', function(event){
			this.handleKeyPress(event);
		}.bindAsEventListener(this));

		// place the cursor on the input field
//		this.searchInput.focus();
	},
	handleBlur: function() {
		// the form has lost focus. Check if results should be removed
		if (this.resultIsVisible) {
			/*
				The result container is to be hidden. However, it cannot be
				removed right away. If the user has clicked a link on the
				result container, this is also treated as a blur event. So
				we delay the hiding process in case a href is clicked.
			*/
			setTimeout(this.doBlur.bind(this), 200);
		}
	},
	doBlur: function(){
		// hide the result container. Clear internal search vars.
		this.resultContainer.addClassName("hidden");
		this.resultIsVisible = false;
		this.activeResult = null;
		this.totalResults = null;
		this.currentSearchString = "";
	},
	navigateResults: function(offset) {
		/*
			Navigate up and down in the search result container.
			Only navigate when there are actual search results.
			When navigating out of the list, the focus is set to the
			search input field.
		*/
		if (this.resultIsVisible && this.totalResults > 0) {
			// clear css on old active
			this.resultContainer.down('div.wrapper', this.activeResult).removeClassName("active");
			
			if (this.activeResult == null) {
				// select first or last item
				if(offset == 1) {
					this.activeResult = 0;
				} else {
					this.activeResult = this.totalResults - 1;
				}
			} else {
				if ((this.activeResult == 0 && offset == -1)
				|| (this.activeResult == this.totalResults -1 && offset == 1)) {
					// jump out of list and into the form
					this.activeResult = null;
				} else {
					// go to next/previous item in the list
					this.activeResult += offset;
				}
			}
			// update active pointer
			if (this.activeResult != null) {
				this.resultContainer.down('div.wrapper', this.activeResult).addClassName("active");
			}
		}
	},
	handleKeyPress: function(event) {
		/*
			Handle enter. This must be picked up in keypress, before the
			built-in autosubmit is triggered. onKeyUp is too late.
			
			If a search hit is selected, then the event is stopped and the
			corresponding url is placed in the window location.
			
			If no search hit is selected, the event continues, triggering the
			normal search.
		*/
		if (event.keyCode == Event.KEY_RETURN) {
			if (this.activeResult != null) {
				// search hit is selected. show that instead
				event.stop();
				var href = this.resultContainer.down('div.wrapper', this.activeResult).down('a').href;
				window.location = href;
			}
		}
	},
	handleKeyUp: function(event) {
		/*
			Triggers navigation on arrow keys up and down.
			Hides search input on arrow keys left and right.
			
			Triggers ajax search when search params have changed
			
			Updates the result container.
		*/

		// behaviour for arrow keys
		switch(event.keyCode) {
			case Event.KEY_UP:
				this.navigateResults(- 1);
				break;
			case Event.KEY_DOWN:
				this.navigateResults(1);
				break;
			case Event.KEY_LEFT:
			case Event.KEY_RIGHT:
				if (this.activeResult != null) {
					// clear css on old active
					this.resultContainer.down('div.wrapper', this.activeResult).removeClassName("active");
					this.activeResult = null;
				}
				break;
		}

		// get search string
		var value = this.searchInput.value;
		
		// remove white space from either side
		value = value.replace(/^\s*/, "").replace(/\s*$/, "");

		if (value.length < 3) {
			//hide result wrapper, clear current search string
			this.resultContainer.addClassName("hidden");
			this.resultContainer.update("");

			this.currentSearchString = "";
			this.totalResults = 0;
			this.resultIsVisible = false;
			this.activeResult = null;

		} else if (value != this.currentSearchString && value.length >= 3) {
			// only search if string has changed since last search
			// and if string is at least 3 chars long (required by cplib)
			
			//show process indicator. hide content
			this.progressContainer.removeClassName("hidden");
			this.resultContainer.addClassName("hidden");
			this.resultIsVisible = false;
			this.activeResult = null;
			this.totalResults = 0;
			
			//save value state
			this.currentSearchString = value;
		
			new Ajax.Request('/xmlhttprequest.php', {
				parameters: {service: "fancysearch.performsearch", searchstring: value},
				method: 'get',
				onSuccess: function(transport) {
					var response = transport.responseText;
					if (response) {
						// convert json to array
						var responseJSON = response.evalJSON();
						this.totalResults = responseJSON.hits;
						
						if (this.totalResults == 0) {
							this.resultContainer.update(responseJSON.message);
						} else {
							var str = "";
							responseJSON.articles.each(function(item){
								str += item;
							}.bind(this));
							this.resultContainer.update(str);
							// add onclick events to the new elements
							this.addClickEventsToResults();
							delete str;
						}
						
						// hide progress. show results
						this.progressContainer.addClassName("hidden");
						this.resultContainer.removeClassName("hidden");
						this.resultIsVisible = true;
						this.activeResult = null;
						
					} else {
						// no response from server
						this.showDefaultResponse();
					}
				}.bind(this),
				onFailure: function(transport) {
					// failure during request
					this.showDefaultResponse();
				}
			});
		}
	},
	showDefaultResponse: function() {
		this.resultContainer.update("Ingen treff");
		this.progressContainer.addClassName("hidden");
		this.resultContainer.removeClassName("hidden");
		this.resultIsVisible = true;
		this.totalResults = 0;
		this.activeResult = null;
	},
	addClickEventsToResults: function() {
		// new result items need onclick events.
		this.resultContainer.select("div.wrapper").each(function(element){
			element.observe("click", function(event) {
				event.stop();
				var el = event.element();
				if (!el.hasClassName("wrapper")) {
					// go up to the wrapper div
					el = el.up('div.wrapper');
				}
				var href = el.down('a').href;
				window.location = href;
			}.bindAsEventListener(this));
		}.bind(this));
	}
});
var mcCannFancySearch;

