var Serializer = new XMLSerializer();
var delay = 200;
var lastKeyTime = 0;

function ASClearInitialValue(name)
{
	if(document.getElementById(name+'asciv').value == 1)
	{
		document.getElementById(name+'asi').value = '';
		document.getElementById(name+'asciv').value = 0;
	}
}

function ASDelayer(name, eventKeyCode)
{
	var newKeyTime = (new Date()).getTime();
	if (lastKeyTime == 0)
	{
		lastKeyTime = newKeyTime;
		return;
	}
	var value = document.getElementById(name+'asi').value;
	var suggKeyword = document.getElementById(name+'asiv').value;
	lastKeyTime = newKeyTime;
	setTimeout('ASSuggest(\''+name+'\','+eventKeyCode+',\''+escape(value)+'\', \''+escape(suggKeyword)+'\');', delay);
}


function ASSuggest(name, eventKeyCode, value, suggKeyword)
{
	value = unescape(value);
	suggKeyword = unescape(suggKeyword);
	if (eventKeyCode == 9 || eventKeyCode == 13 || eventKeyCode == 27 || eventKeyCode == 38 || eventKeyCode == 40 || eventKeyCode == 37 || eventKeyCode == 39)
	{	//Handled @ onKeyDown or no need to react.
		return;
	}
	
	if (value == suggKeyword)
	{
		return;
	}
	
	if (value == '')
	{
		ASClear(name, value);
		return;
	}
	
	if (ajaxXmlDoc[name])
	{
	
		var newKeyTime = (new Date()).getTime();
		//I have no idea why, but sometimes the function triggers sooner than specified by the timeout.
		if (newKeyTime - lastKeyTime < delay*0.9)
		{
			return;
		}
		
		ASClear(name, value);
		
		toggle_element_visibility(name+'ass', '');
		var suggElem = document.getElementById(name+'ass');
		suggElem.innerHTML = '';
		
		var sXpath = '/Suggestions/n/text()';
		var keywordNodes = new Array();
		try
		{
			keywordNodes = ajaxXmlDoc[name].selectNodes(sXpath);
		}
		catch(e)
		{
			return;
		}
		
		value = get_search_safe_string(value.toLowerCase());
		var maxcount = 15;
		var count=0;
		var secondary_list = new Array();
		var secondary_list_positions = new Array();
		
		for (var i=0; i<keywordNodes.length; i++)
		{
			var keywordNode = keywordNodes[i];
			var sugg = decode_xml_special_chars(Serializer.serializeToString(keywordNode));
			var sugg_lower = sugg.toLowerCase();
			var sugg_lower_pos = sugg_lower.search(value);
			
			if (sugg_lower_pos === 0)
			{
				count++;
				suggElem.innerHTML = suggElem.innerHTML + ASGetLink(name, count, sugg, value.length, 0);
			}
			else if (sugg_lower_pos != -1 && secondary_list.length < maxcount)
			{
				secondary_list[secondary_list.length] = sugg;
				secondary_list_positions[secondary_list_positions.length] = sugg_lower_pos;
			}
			
			if (count>=maxcount)
			{
				break;
			}
		}
		
		if ((count + secondary_list.length) == 0)
		{
			ASClear(name);
			return;
		}
		
		for (var i=0; i<secondary_list.length; i++)
		{
			if (count + i >= maxcount)
			{
				break;
			}
			suggElem.innerHTML = suggElem.innerHTML + ASGetLink(name, (count+i+1), secondary_list[i], value.length, secondary_list_positions[i]);
		}
		ieFixSelect(name+"ass","hidden");
	}
}


function ASGetLink(name, count, sugg, value_length, value_pos)
{
	return '<a href="javascript: void(0);" id="'+name+'ASLink'+count+'" class="" onMouseOver="ASHandleMouseOver(\''+name+'\','+count+');" onMouseDown="ASSubmit(\''+name+'\', this.innerHTML)">' + sugg.substring(0,value_pos)+'<b>'+sugg.substring(value_pos, value_pos+value_length)+'</b>'+sugg.substring(value_pos+value_length) + '</a>';
}


function ASClear(name, value)
{
	ieFixSelect(name+'ass','visible');
	toggle_element_visibility(name+'ass', 'none');
	document.getElementById(name+'ass').innerHTML = '';
	if (value != null)
	{
		document.getElementById(name+'asiv').value = value;
	}
	document.getElementById(name+'assi').value = 0;
}


function ASHandleMouseOver(name, newId)
{
	var selectedIdVal = parseInt(document.getElementById(name+'assi').value);
	ASChangeActiveElement(name, selectedIdVal, newId, false);
}


function ASSubmit(name, value)
{
	var asi = document.getElementById(name+'asi');
	asi.value=strip_tags(decode_xml_special_chars(value));
	asi.form.submit();
}


function ASChangeActiveElement(name, curId, newId, changeKeyword)
{
	var keyword = document.getElementById(name+'asi');
	if (curId > 0)
	{
		var current = document.getElementById(name+'ASLink'+curId);
		current.className = '';
	}
	else if (curId == 0)
	{
		var suggKeyword = document.getElementById(name+'asiv');
		suggKeyword.value = keyword.value;
	}
	
	var suggSize = document.getElementById(name+'ass').getElementsByTagName('a').length;
	if (newId < 0)
	{
		newId = suggSize;
	}
	else if (newId > suggSize)
	{
		newId = 0;
	}
	
	if (newId == 0)
	{
		var suggKeyword = document.getElementById(name+'asiv');
		keyword.value = suggKeyword.value;
	}
	else
	{
		var newElem = document.getElementById(name+'ASLink'+newId);
		newElem.className = name+'ASSelected';
		if (changeKeyword)
		{
			keyword.value = strip_tags(decode_xml_special_chars(newElem.innerHTML));
		}
	}
	
	var selectedId = document.getElementById(name+'assi');
	selectedId.value = newId;
}


function ASHandleKeyboardSelect(name, eventKeyCode)
{
	if (eventKeyCode != 38 && eventKeyCode != 40 && eventKeyCode != 27)
	{
		return;
	}
	
	var selectedIdVal = parseInt(document.getElementById(name+'assi').value);
	
	if (eventKeyCode == 27)
	{
		ASChangeActiveElement(name, selectedIdVal, 0, true);
		ASClear(name);
		return;
	}
	
	var newId = 0;
	if (eventKeyCode == 38)
	{
		newId = selectedIdVal - 1;
	}
	else if (eventKeyCode == 40)
	{
		newId = selectedIdVal + 1;
	}
	
	ASChangeActiveElement(name, selectedIdVal, newId, true);
}

function ieFixSelect(elem,action){
	if(navigator.userAgent.toLowerCase().indexOf("msie")>-1 && !window.opera){
		version = navigator.userAgent.toLowerCase().match(/msie\s(\d+(\.?\d)*)/)[1];
		dot_pos = version.toString().indexOf(".");
		if(dot_pos > -1){
			majorversion = this.version.toString().slice(0, dot_pos);
		}
		if(majorversion<=6){
			var x = document.getElementById(elem);
			x.ieFix = ieFixGetElem(x, document.getElementsByTagName("select"));
			for(var i = x.ieFix.length; i; x.ieFix[--i].style.visibility = action);		
		}
	}
}

ieFixGetElem = function(o, l){
	function getOffset(o){
		for(var r = {l: o.offsetLeft, t: o.offsetTop, r: o.offsetWidth, b: o.offsetHeight};
			o = o.offsetParent; r.l += o.offsetLeft, r.t += o.offsetTop);
		return r.r += r.l, r.b += r.t, r;
	}
	var a = arguments, j = a.length;
	j > 2 && (o = {offsetLeft: o, offsetTop: l, offsetWidth: j == 5 ? a[2] : 0,
	offsetHeight: j == 5 ? a[3] : 0, offsetParent: null}, l = a[j - 1]);
	for(var b, s, r = [], a = getOffset(o), j = isNaN(l.length), i = (j ? l = [l] : l).length; i;
		b = getOffset(l[--i]), (a.l == b.l || (a.l > b.l ? a.l <= b.r : b.l <= a.r))
		&& (a.t == b.t || (a.t > b.t ? a.t <= b.b : b.t <= a.b)) && (r[r.length] = l[i]));
	return j ? !!r.length : r;
};
