var textboxObj;
var textboxDiv;
var divObj = null;
var SelectedRowIndex = -1;
var state = 'idle';
var actualTextValue = '';
var loadingText = 'Loading...';
var autocompleteStylePrefix = '';

var minAutoCompleteChars = 2;
var MaxRowsShown = 5;
var rowHeight = 17;
var overflow = false;
var MaxRowsCount = 500;
var autocompleteDelay = 100;
var timeoutDelay = 5000;

var navigatorAgt=navigator.userAgent.toLowerCase();

/* Array which should hold autocomplete data*/
var showInfo=true;
var autocompleteArray=new Array();

/*Variables which contain information on default textbox values*/
var textbox_default_value = '';

function showAutocomplete() {
	if (!divObj) {
		return;
	}
	var size = autocompleteArray.length;
	if (size == 0) {
		changeAutocompleteState('idle');
		return;
	}
	divObj.innerHTML = getInnerHTML();
	//if overflow - limit height
	//rowHeight = divObj.firstChild.offsetHeight;
	if (size <= MaxRowsShown) {
		divObj.style.height = rowHeight * size + 'px';
		divObj.style.overflowY = 'hidden';
		overflow = false;
	} else {
		divObj.style.height = rowHeight * MaxRowsShown + 'px';
		divObj.style.overflowY = 'auto';
		overflow = true;
	}
	divObj.style.display = 'inline';
	textboxObj.onkeydown = acTextboxKeyDown;
	textboxObj.onblur = acTextboxOut;
	SelectedRowIndex = -1;
}
function showLoadingInfo() {
	if (!divObj) {
		return;
	}
	divObj.innerHTML = getLoadingInnerHTML();
	//rowHeight = divObj.firstChild.offsetHeight;
	divObj.style.height = rowHeight + 'px';
	divObj.style.display = 'inline';
}
function hideAutocomplete() {
	if (!divObj) {
		return;
	}
	divObj.style.display = 'none';
	textboxObj.onkeydown = '';
	textboxObj.onblur = '';
	actualTextValue = textboxObj.value;
}
function createAutocomplete(textBox,parentNode,stylePrefix) {
	if (textboxObj && (textboxObj != textBox)) {
		closeAutocomplete();
	}
	autocompleteStylePrefix = stylePrefix;
	if (!divObj) {
		divObj = document.createElement("DIV");
		divObj.id="autocomplete_div";
		divObj.className=getStyleWithPrefix('autocomplete');
		divObj.style.display = "none";
	}
	
	textboxObj = textBox;
	textboxDiv = parentNode;
	
	var textboxLoc = getAbsLocation(textBox);
	var parentLoc = getAbsLocation(textboxDiv);
	
	divObj.style.left = textboxLoc['x'] - parentLoc['x'] + 'px';
	divObj.style.top = textboxLoc['y'] - parentLoc['y'] + textBox.offsetHeight + 'px';
	divObj = textboxDiv.appendChild(divObj);
	
	textboxObj.onkeyup = acTextboxKeyUp;
	actualTextValue = textboxObj.value;
}
function closeAutocomplete() {
	changeAutocompleteState('idle');
	if (!divObj) {
		return;
	}
	if (textboxDiv) {
		textboxDiv.removeChild(divObj);
		textboxDiv = null;
	}
	textboxObj.onkeyup = '';
	divObj = null;
	autocompleteStylePrefix = '';
}

function getInnerHTML() {
	var result = '';
	var autocomplete_item_1_style = 'autocomplete_item_1';
	if (showInfo && autocompleteArray.length > MaxRowsShown) {
		autocomplete_item_1_style = 'autocomplete_item_1_short';
	}
	for (var i = 0; i< autocompleteArray.length; i++) {
		var text = autocompleteArray[i]['text'];
		if (showInfo)
			var info = autocompleteArray[i]['info'];
		result +=
			'<div id="autocomplete_div_'+i+'" class="'+getStyleWithPrefix('autocomplete_item')+'" onmouseover="acMouseOver('+i+');" onmouseout="acMouseOut('+i+');">' +
			'<a href="javascript:acClick('+i+');">' +
			'<div class="'+getStyleWithPrefix(autocomplete_item_1_style)+'">' + text + '</div>'+
			(showInfo ? ('<div class="'+getStyleWithPrefix('autocomplete_item_2')+'">' + info + '</div>') :  "" ) +
			'</a></div>';
	}
	return result;
}
function getLoadingInnerHTML() {
	return '<div class="'+getStyleWithPrefix('autocomplete_item_loading')+'">'+loadingText+'</div>';
}
var selectedByMouse = false;
function select(pos) {
	if (SelectedRowIndex != -1)
		acMouseOut(SelectedRowIndex);
	$('autocomplete_div_'+pos).className = getStyleWithPrefix('autocomplete_item_selected');
	SelectedRowIndex = pos;
	selectedByMouse = false;
}
function deselect(pos) {
	$('autocomplete_div_'+pos).className = getStyleWithPrefix('autocomplete_item');
	if (SelectedRowIndex == pos) {
		SelectedRowIndex = -1;
	}
}
function acMouseOver(pos) {
	select(pos);
	selectedByMouse = true;
}
function acMouseOut(pos) {
	deselect(pos);
}
function acClick(pos) {
	SelectedRowIndex = pos;
	if (SelectedRowIndex != -1) {
		fillInCity();
	}
}

function fillInCity() {
	textboxObj.value = autocompleteArray[SelectedRowIndex]['text'];
	changeAutocompleteState('idle');
	textboxObj.focus();
	if (typeof onAutocompleteSelect == 'function') {
		onAutocompleteSelect();
	}
}
function changeSelection(dif) {
	var newIndex = SelectedRowIndex+dif;
	if ((newIndex >= 0) && (newIndex <autocompleteArray.length)) {
		select(newIndex);
		if (overflow) {
			if (dif < 0) {
				var topToBeShown = SelectedRowIndex * rowHeight;
				if (divObj.scrollTop > topToBeShown)
					divObj.scrollTop = topToBeShown;
			} else if (dif > 0) {
				//check move down
				var topToBeShown = (SelectedRowIndex - MaxRowsShown + 1)* rowHeight;
				if (divObj.scrollTop < topToBeShown)
					divObj.scrollTop = topToBeShown;
			}
		}
	}
}

function acTextboxKeyDown (e) {
	if (state != 'selecting')
		return;
	var keyKode;
	if (isIE) {
		keyKode = event.keyCode;
	} else {	
		keyKode = e.which;
	}
	switch(keyKode) {
		case 40:
			//down
			changeSelection(1);
			return false;
			break;
		case 38:
			//up
			changeSelection(-1);
			return false;
			break;
		case 13:
			if (SelectedRowIndex != -1) {
				fillInCity();
				return false;
			} else {
				changeAutocompleteState('idle');
				return false;
			}
			break;
		case 46:
		case 27:
			changeAutocompleteState('idle');
			return false;
		break;
	}
}
function acTextboxOut() {
	if(divObj!=null) {
		if( divObj.style.display == "inline" && SelectedRowIndex != -1 && selectedByMouse) {
			//Fill in city
			fillInCity();
		} else {
			closeAutocomplete();
		}
	}
}
function acTextboxKeyUp() {
	//main enter for suggesting
	if (actualTextValue == textboxObj.value) {
		return;
	}
	actualTextValue = textboxObj.value;
	var textValue = textboxObj.value;
	if (textValue.length >= minAutoCompleteChars) {
		//switch to wait mode;
		changeAutocompleteState('waiting');
		window.setTimeout( function() { optionalStartSuggesting(textValue); },autocompleteDelay);
	} else {
		changeAutocompleteState('idle');
	}
}
function optionalStartSuggesting(textValue) {
	if ((textValue == textboxObj.value) && (state == 'waiting')) {
		//testbox value have not been changed - set state to loading and call method to fill autocomplete
		changeAutocompleteState('loading');
		actualTextValue = textValue;
		fillAutocompleteData(textValue,MaxRowsCount);
		window.setTimeout( function() { loadingTimeout(textValue); },timeoutDelay);
	}
}
function optionalShowAutocomplete(textValue) {
	if ((state == 'loading') && (actualTextValue == textValue) ) {
		changeAutocompleteState('selecting');
	}
}
function changeAutocompleteState(newState) {
	if (newState == state)
		return;
	if ((state == 'loading') || (state == 'selecting')) {
		hideAutocomplete();
	}
	state = newState;
	if (state == 'loading') {
		showLoadingInfo();
	} else if (state == 'selecting') {
		showAutocomplete();
	}
}
function loadingTimeout(textValue) {
	if ((state == 'loading') && (actualTextValue == textValue) ) {
		changeAutocompleteState('idle');
	}
}
function getStyleWithPrefix(style) {
	if (autocompleteStylePrefix) {
		return autocompleteStylePrefix + "_" + style;
	} else {
		return style;
	}
}

