var g_arrAsFields = [];

function addAutoSuggestField(f_strTextBoxId, f_arrSuggestions, f_strDivClassName, f_intListLength, f_strOnChangeEval)
{
	var objAs = new autoSuggest(f_strTextBoxId, f_arrSuggestions, f_strDivClassName, f_intListLength, f_strOnChangeEval);
	if (objAs)
	{
		g_arrAsFields.push(objAs);
	}
	return objAs;
}

function updateAutoSuggestions(f_strTextBoxId, f_arrSuggestions)
{
	for (var i = 0; i < g_arrAsFields.length; i++)
	{
		if (g_arrAsFields[i] && g_arrAsFields[i].field.id == f_strTextBoxId)
		{
			g_arrAsFields[i].clearList();
			g_arrAsFields[i].clearCache();
			if (f_arrSuggestions)
			{
				g_arrAsFields[i].suggestions = f_arrSuggestions;
			}
			else
			{
				g_arrAsFields[i].suggestions = new Array();
			}
			break;
		}
	}
}

// AUTOSUGGEST CLASS

var autoSuggest = function(f_strTextBoxId, f_arrSuggestions, f_strDivClassName, f_intListLength, f_strOnChangeEval)
{
	if (!document.getElementById || !f_strTextBoxId || !f_arrSuggestions)
	{
		return null;
	}

	this.field = document.getElementById(f_strTextBoxId);
	if (!this.field)
	{
		return null;
	}

	this.listCssClass = f_strDivClassName;
	//this.listCreated = this.createList();
	this.listCreated = false;
	this.suggestions = f_arrSuggestions;
	this.cache = new Array();
	this.selectedIndex = -1;
	this.lastTyped = '';
	if (!f_intListLength)
	{
		f_intListLength = 10;
	}
	this.listLength = f_intListLength;
	this.onChangeEval = f_strOnChangeEval;

	var objPointer = this;
	this.field.onkeypress = function(f_objEvent)
	{
		return objPointer.handleKeyPress(f_objEvent);
	}
	this.field.onkeyup = function(f_objEvent)
	{
		return objPointer.showList(f_objEvent);
	}
	/*
	this.field.onblur = function(f_objEvent)
	{
		return objPointer.clearList();
	}
	*/
	this.field.onclick = function(f_objEvent)
	{
		return objPointer.clearList();
	}
	this.field.onmouseover = function(f_objEvent)
	{
		return objPointer.dimItem();
	}
}

autoSuggest.prototype.createList = function()
{
	var blnCreated = false;

	var objPos = findPosition(this.field);
	this.div = document.createElement('div');
	
	if (objPos.found && this.field.offsetWidth && this.field.offsetParent)
	{
		this.div.id = this.field.id + '_suggestDiv';
		this.div.className = this.listCssClass;
		this.div.style.position = 'absolute'
		this.div.style.zIndex = '100'
		this.div.style.visibility = 'hidden';

		this.div.style.top = (objPos.top + this.field.offsetHeight) + 'px';
		this.div.style.left = objPos.left + 'px';
		this.div.style.width = (this.field.offsetWidth - 2) + 'px';
		this.field.offsetParent.appendChild(this.div);
		
		blnCreated = true;
	}

	return blnCreated;
}

autoSuggest.prototype.showList = function(f_objEvent)
{
	if (!f_objEvent)
	{
		f_objEvent = event;
	}
	if (!f_objEvent)
	{
		return;
	}
	
	if (!this.listCreated)
	{
		this.listCreated = this.createList();
		if (!this.listCreated)
		{
			return;
		}
	}
	
	var blnControlKey = this.browse(f_objEvent);
	if (blnControlKey)
	{
		return false;
	}

	var strTyped = this.field.value.toLowerCase();
	var strSuggestion = '';
	var strTypedFirstChar = '';
	var strSuggestionFirstChar = '';
	var strPreviousFirstChar = '';
	var arrMatches = new Array();
	var blnCached = false;

	this.clearList();

	if (strTyped.length > 0)
	{
		if (this.lastTyped.length != 0 && strTyped.length > this.lastTyped.length && strTyped.indexOf(this.lastTyped) == 0)
		{
			// New char appended
			for (var i = 0; i < this.cache.length; i++)
			{
				if (this.cache[i] && this.cache[i].length >= strTyped.length)
				{
					strSuggestion = this.cache[i].toLowerCase();
					if (strSuggestion.indexOf(strTyped) == 0)
					{
						arrMatches.push(this.cache[i]);
					}
				}
			}
		}
		else
		{
			strTypedFirstChar = strTyped.substr(0, 1);
			for (var i = 0; i < this.suggestions.length; i++)
			{
				if (this.suggestions[i] && this.suggestions[i].length >= strTyped.length)
				{
					strSuggestion = this.suggestions[i].toLowerCase();
					strSuggestionFirstChar = strSuggestion.substr(0, 1);

					if (strPreviousFirstChar.length != 0 && strSuggestionFirstChar != strPreviousFirstChar && strTypedFirstChar != 'v' && strTypedFirstChar != 'w')
					{
						break;
					}
					else if (strSuggestion.indexOf(strTyped) == 0)
					{
						arrMatches.push(this.suggestions[i]);
						strPreviousFirstChar = strSuggestionFirstChar;
					}
				}
			}
		}

		if (arrMatches.length == 1 && arrMatches[0].toLowerCase() == strTyped)
		{
			arrMatches = [];
		}
		else if (arrMatches.length != 0)
		{
			this.fillList(arrMatches);
			this.selectedIndex = -1;
			if (this.listLength != 0 && this.listLength < arrMatches.length)
			{
				this.div.style.height = (this.listLength * this.div.childNodes[0].offsetHeight + 2) + 'px';
				this.div.style.overflowY = 'scroll';
			}
			else
			{
				this.div.style.height = 'auto';
				this.div.style.overflowY = 'visible';
			}
			this.div.style.visibility = 'visible';
		}
	}

	this.lastTyped = strTyped;
	this.cache = arrMatches;

	return true;
}

autoSuggest.prototype.fillList = function(f_arrItems)
{
	for (i = 0; i < f_arrItems.length; i++)
	{
		this.addItem(f_arrItems[i], i);
	}
}

autoSuggest.prototype.addItem = function(f_strContent, f_intIndex)
{
	var objItem = document.createElement('div');

	objItem.id = this.div.id + '_' + f_intIndex;
	objItem.className = 'asItem';
	objItem.innerHTML = f_strContent;

	var objPointer = this;
	objItem.onmouseover = function(f_objEvent)
	{
		objPointer.highlightItem(f_intIndex, true);
		return true;
	}
	/*
	objItem.onmouseout = function(f_objEvent)
	{
		objPointer.dimItem(f_intIndex);
		return true;
	}
	*/
	objItem.onmousedown = function(f_objEvent)
	{
		objPointer.selectItem(f_intIndex);
		return true;
	}

	this.div.appendChild(objItem);
}

autoSuggest.prototype.clearList = function()
{
	this.selectedIndex = -1;
	if (this.div)
	{
		this.div.style.visibility = 'hidden';
		this.div.innerHTML = '';
	}
	return true;
}

autoSuggest.prototype.clearCache = function()
{
	this.cache = [];
	return true;
}

autoSuggest.prototype.handleKeyPress = function(f_objEvent)
{
	if (!f_objEvent)
	{
		f_objEvent = event;
	}
	if (!f_objEvent)
	{
		return;
	}
	
	var blnCancel = false;

	switch (f_objEvent.keyCode)
	{
		case 40:
			// Arrow down
			if (this.cache.length > 0)
			{
				blnCancel = true;
			}
			break;
		case 38:
			// Arrow up
			if (this.cache.length > 0)
			{
				blnCancel = true;
			}
			break;
		case 13:
			// Enter
			if (this.selectedIndex > -1)
			{
				this.selectItem();
			}
			blnCancel = true;
			break;
	}
	if (blnCancel)
	{
		return false;
	}
	else
	{
		return true;
	}
}

autoSuggest.prototype.browse = function(f_objEvent)
{
	if (!f_objEvent)
	{
		f_objEvent = event;
	}
	if (!f_objEvent)
	{
		return;
	}
	
	var blnControlKey = false;

	if (this.cache.length == 0)
	{
		return false;
	}

	switch (f_objEvent.keyCode)
	{
		case 40:
			// Arrow down
			this.browseDown();
			blnControlKey = true;
			break;
		case 38:
			// Arrow up
			this.browseUp();
			blnControlKey = true;
			break;
		case 27:
			// Esc
			this.clearList();
			//this.cache = [];
			blnControlKey = true;
			break;
		case 13:
		case 16:
		case 17:
		case 18:
		case 37:
		case 39:
			// Enter, Shift, Ctrl, Alt, Arrow left, Arrow right
			blnControlKey = true;
			break;
	}

	return blnControlKey;
}

autoSuggest.prototype.browseDown = function()
{
	var intSelect = -1;

	if (this.selectedIndex == -1)
	{
		intSelect = 0;
	}
	//else if (this.selectedIndex == this.cache.length - 1)
	//{
	//	intSelect = 0;
	//}
	else if (this.selectedIndex == this.cache.length - 1)
	{
		intSelect = -1;
	}
	else
	{
		intSelect = this.selectedIndex + 1;
	}

	this.highlightItem(intSelect, true);
}

autoSuggest.prototype.browseUp = function()
{
	var intSelect = -1;

	if (this.selectedIndex == -1)
	{
		intSelect = this.div.childNodes.length - 1;
	}
	//else if (this.selectedIndex == 0)
	//{
	//	intSelect = this.cache.length - 1;
	//}
	else
	{
		intSelect = this.selectedIndex - 1;
	}

	this.highlightItem(intSelect, true);
}

autoSuggest.prototype.highlightItem = function(f_intIndex, f_blnDimCurrent)
{
	if (f_blnDimCurrent)
	{
		this.dimItem(this.selectedIndex);
	}
	if (f_intIndex > -1)
	{
		var objItem = this.div.childNodes[f_intIndex];
		objItem.className = 'asHighlighted';
		this.selectedIndex = f_intIndex;

		if (objItem.offsetTop < this.div.scrollTop)
		{
			//scroll up to the highlighted row
			this.div.scrollTop = objItem.offsetTop
		}
		else
		{
			var intBottom = objItem.offsetTop + objItem.clientHeight;
			if (intBottom > this.div.scrollTop + this.div.clientHeight)
			{
				this.div.scrollTop = intBottom - this.div.clientHeight;
			}
		}

	}
}

autoSuggest.prototype.dimItem = function(f_intIndex)
{
	if (!f_intIndex || f_intIndex < 0)
	{
		f_intIndex = this.selectedIndex;
	}
	if (f_intIndex > -1)
	{
		this.div.childNodes[f_intIndex].className = 'asItem';
		this.selectedIndex = -1;
	}
}

autoSuggest.prototype.selectItem = function(f_intIndex)
{
	if (!f_intIndex || f_intIndex < 0)
	{
		f_intIndex = this.selectedIndex;
	}
	if (f_intIndex > -1)
	{
		this.field.value = this.cache[f_intIndex];
		this.field.focus();
		this.clearList();
		this.clearCache();
		
		if (this.onChangeEval)
		{
			eval(this.onChangeEval);
		}
	}
}

// MISC HELPERS

function debug(f_str)
{
	document.getElementById('txtDebug').value += f_str + ' ';
}

