var autoSuggestProvider = Class.create();

autoSuggestProvider.prototype = {

		box:null,
		suggestionContainer:null,
		url:null,
		
		startCharCount: 3, //default character count for starting ajax
		
		result: new Array(),
		resultBackup: new Array(),
		highlight: -1,
		_noHist: false,

		params: "",	
		
		initialize: function (textBoxID, suggestionContainerID, processorURL, startCharCount)
		{
			this.box = $(textBoxID);
			this.suggestionContainer = $(suggestionContainerID);
			this.url = processorURL;
			
			if (startCharCount != null)
				this.startCharCount = startCharCount;
			
			//assign event to the box
			Event.observe(this.box, "keyup", 
				this.captureKey.bind(this),
				false);	
			/*	
			Event.observe(this.box, "blur", 
				this.hideContainer.bind(this),
				false);	*/						
			
		},
		
		
		removeBold: function (value)
		{
			//remove bolds
			value = value.replace(/\<b\>/g, "");
			value = value.replace(/\<\/b\>/g, "");
			value = value.replace(/\<B\>/g, "");
			value = value.replace(/\<\/B\>/g, "");			
			
			return value;					
		},

		pickItem: function (value)
		{
			value = this.removeBold(value);
		
			this.box.value = value;
			this.suggestionContainer.style.display="none";
		},
		
		pickEntry: function (e)
		{
			value = this.removeBold(Event.element(e).innerHTML);
		
			this.box.value = value;
			this.suggestionContainer.style.display="none";
		},
		
		captureKey: function (e)
		{
			var keyCode;
			
			if (window.event) {		
					keyCode = event.keyCode;								
				}
			else {
					keyCode = e.keyCode;
				}		
			
			if (Event.element(e).id == this.box.id)
			{

				if (keyCode == 13)
				{
					if (this.result.length > 0) {
						if (this.highlight == -1)
							this.pickItem(this.result[0]);
						else
							this.pickItem( this.result[this.highlight]);
						this.hideSuggestion();
					}
					this.hilight = -1;
				}
				else if (keyCode == 40)
				{
					
					if ((this.result.length > 0)&&(this.suggestionContainer.style.display != "none")) {					
						if (this.highlight < this.result.length - 1)		{	
							this.highlight++;							
							$("suggest_" + this.highlight).className = "suggestItemOn";
							if ( $("suggest_" + (this.highlight-1)) != null )
							{
								$("suggest_" + (this.highlight-1)).className = "suggestItem";
							}
						}

					}				
				}
				else if (keyCode == 38)
				{
					if ((this.result.length > 0)&&(this.suggestionContainer.style.display != "none")) {
						if (this.highlight > 0)		{	
							this.highlight--;							
							$("suggest_" + this.highlight).className = "suggestItemOn";

							if ( $("suggest_" + (this.highlight+1)) != null ){
								$("suggest_" + (this.highlight+1)).className = "suggestItem";
							}
						}
				
					}				
				}			
				else
				{
				
					var catInput = this.box;
					if (catInput.value.length == this.startCharCount)
					{
						//if characters count met, send ajax request
						this.request();
					}
					else if (catInput.value.length > this.startCharCount)
					{
						//otherwise, perform internal filtering
						this.limitSuggestion();
					}
					else
					{
						this.hideSuggestion();
					}
				}
			}
		},
		
		//if only 1 choice, auto-complete
		autoComplete: function()
		{
			if (this.result.length == 1)
			{
				this.pickItem(this.result[0])
				this.box.blur();
				this.hideSuggestion();
			}
			else if (this.result.length > 1)
			{
				this.dispSuggestion(); 						
			}
			else
			{
				this.hideSuggestion();
			}
		},
		
		limitSuggestion: function()
		{
			this.highlight = -1;
		
			var cat = this.box.value;
			
			this.result = this.resultBackup.slice();
			
			//filter result array
			var i=0;

			for (i=this.result.length-1;i>=0;i--)
			{
				
				if (this.removeBold(this.result[i]).toLowerCase().indexOf( cat.toLowerCase() ) == -1)
					this.result.splice(i, 1);
			}
			
			this.autoComplete();
			
			
		},
		
		request: function ()
		{
			highlight = -1;
			var url = this.url;
			var params = "initial=" + this.box.value;
			
			var opt = {
					method: "post",
					parameters: params,
					onSuccess: this.requestDone.bind(this),
					onFailure: function(resp) {
						alert('Error ' + resp.status + ' -- ' + resp.statusText);
					}
				};
		
			new Ajax.Request(url, opt);			
		},
		
		requestDone: function (resp)
		{

			var fb = resp.responseText;
			var temp = eval("(" + fb + ")");
			if (temp.entries.length > 0)
				this.result = temp.entries;
				
				
			this.resultBackup = this.result.slice();

			this.autoComplete();
			
		},
		
		dispSuggestion: function ()
		{
			var dispHTML = "";
			var i=0;
			for (i=0;i<this.result.length;i++)
			{
				var hiliteItem = hiliteMan.highlightSearchTerms (this.box.value, this.result[i], true, false, "<b>", "</b>")
				dispHTML += "<span id=\"suggest_" + i + "\" style='cursor:hand;display:block;color:black' class='suggestItem' >" + hiliteItem + "</span>";
			}
			
			//bring the div to the right place
			var suggestDiv = this.suggestionContainer;
			suggestDiv.innerHTML = dispHTML;
			
			//assign clicking events to all items
			for (var i=0; i<suggestDiv.children.length; i++)
			{
				Event.observe(suggestDiv.children[i], "click", 
					this.pickEntry.bind(this),
					false);					
			}
			

			suggestDiv.style.width = this.box.offsetWidth;	
			
			var left = this.getRealPos(this.box, "Left");
			var top = this.getRealPos(this.box, "Top") + this.box.offsetHeight + 1;
			
			suggestDiv.style.left = left;
			suggestDiv.style.top = top;
			
			suggestDiv.style.display = "block";	
			
			return null;			
		},
		
	
		hideSuggestion: function()
		{
			var suggestDiv = this.suggestionContainer;
			suggestDiv.innerHTML = "";
			suggestDiv.style.display = "none";					
		},
		
		getRealPos: function(el,which) 
		{
			iPos = 0
			while (el!=null) {
	 			iPos += el["offset" + which]
				el = el.offsetParent
			}
			return iPos
		}		
	};		
	
//static object to invoke hilite
var hiliteMan = {
	/*
	* This is the function that actually highlights a text string by
	* adding HTML tags before and after all occurrences of the search
	* term. You can pass your own tags if you'd like, or if the
	* highlightStartTag or highlightEndTag parameters are omitted or
	* are empty strings then the default <font> tags will be used.
	*/
	doHighlight: function (bodyText, searchTerm, highlightStartTag, highlightEndTag) 
	{
		// the highlightStartTag and highlightEndTag parameters are optional
		if ((!highlightStartTag) || (!highlightEndTag)) {
			highlightStartTag = "<font style='color:blue; background-color:yellow;'>";
			highlightEndTag = "</font>";
		}
			
		// find all occurences of the search term in the given text,
		// and add some "highlight" tags to them (we're not using a
		// regular expression search, because we want to filter out
		// matches that occur within HTML tags and script blocks, so
		// we have to do a little extra validation)
		var newText = "";
		var i = -1;
		var lcSearchTerm = searchTerm.toLowerCase();
		var lcBodyText = bodyText.toLowerCase();
			
		while (bodyText.length > 0) {
			i = lcBodyText.indexOf(lcSearchTerm, i+1);
			if (i < 0) {
			newText += bodyText;
			bodyText = "";
			} else {
			// skip anything inside an HTML tag
			if (bodyText.lastIndexOf(">", i) >= bodyText.lastIndexOf("<", i)) {
				// skip anything inside a <script> block
				if (lcBodyText.lastIndexOf("/script>", i) >= lcBodyText.lastIndexOf("<script", i)) {
				newText += bodyText.substring(0, i) + highlightStartTag + bodyText.substr(i, searchTerm.length) + highlightEndTag;
				bodyText = bodyText.substr(i + searchTerm.length);
				lcBodyText = bodyText.toLowerCase();
				i = -1;
				}
			}
			}
		}
			
		return newText;
	},


	/*
	* This is sort of a wrapper function to the doHighlight function.
	* It takes the searchText that you pass, optionally splits it into
	* separate words, and transforms the text on the current web page.
	* Only the "searchText" parameter is required; all other parameters
	* are optional and can be omitted.
	*/
	highlightSearchTerms: function (searchText, fieldStr, treatAsPhrase, warnOnFailure, highlightStartTag, highlightEndTag)
	{
	// if the treatAsPhrase parameter is true, then we should search for 
	// the entire phrase that was entered; otherwise, we will split the
	// search string so that each word is searched for and highlighted
	// individually
	if (treatAsPhrase) {
		searchArray = [searchText];
	} else {
		searchArray = searchText.split(" ");
	}
		
		
	var bodyText = fieldStr;
	for (var i = 0; i < searchArray.length; i++) {
		bodyText = this.doHighlight(bodyText, searchArray[i], highlightStartTag, highlightEndTag);
	}  

	return bodyText;
	}
};	
