var boxClass = 'suggestBox';
var headerClass = 'suggestHeader';
var itemClass = 'suggestItem';
var itemOverClass = 'suggestItemOver';
var valueClass = 'suggestValue';
var moreClass = 'suggestMore';

var ExtraWidth = 2;	// Factor to increase knockout window above textbox
var form = null;
var submitFunction = null;
var txtbox = null;
var iatabox = null;
var url = null;
var fullUrl = null;		// url, including locale
var cache = new Object();
var text = '';
var lastVal = '';
var closing = false;
var hasXml = false;
var req = null;
var currentText = '';
var currentKeyCode = '';
var currentIndex = -1;
var currentItem = null;
var rowCount = -1;
var suggestRows = null;	// an array of div elements
var itemTagName = 'div';
var popup = null;		// a reference to the suggest popup
var locale = null;
var lastKeyCode = -1;	// last key pressed
var activeCalls = 0;
var hideFrame = null;	// IFrame.
var isKeyPressed = false;
var isMorePressed = false;
var isVisible = false;
var imgAnimation = null;
var fullSearch = false;
var hideFullSearch = false;
var bCheckInput = false;

var strings = {
	noairports:TXT_NO_AIRPORTS,
	topsection:TOP_SECTION,
	bottomsection:BOTTOM_SECTION,
	findplaces:TXT_FIND_PLACES,
	extraparams:EXTRA_PARAMS,
	fullparams:FULL_PARAMS
};

function SetStrings(noairports,topsection,bottomsection,findplaces,extraparams,fullparams){
	strings.noairports = noairports;
	strings.topsection = topsection;
	strings.bottomsection = bottomsection;
	strings.findplaces = findplaces;
	strings.extraparams = extraparams;
	strings.fullparams = fullparams;
}

function UnInstall(){
	if(GetItemById('completeDiv')){
		var elem = GetItemById('completeDiv');
		if(elem && elem.parentNode){ elem.parentNode.removeChild(elem); }
	}
	if(GetItemById('hideFrame')){
		var elem = GetItemById('hideFrame');
		if(elem && elem.parentNode){ elem.parentNode.removeChild(elem); }
	}

	lastVal = '';
	closing = false;
	text = '';
	currentText = '';
	currentKeyCode = '';
	currentIndex = -1;
	currentItem = null;
	rowCount = -1;
	suggestRows = null;
	itemTagName = 'div';
	form = null;
	popup = null;
	iatabox = null;
	locale = null;
	lastKeyCode = -1;
	hasXml = false;
	fullUrl = null;
	url = null;
	activeCalls = 0;
	hideFrame = null;
	fullSearch = false;
	hideFullSearch = false;
	SetStrings(TXT_NO_AIRPORTS,TOP_SECTION,BOTTOM_SECTION,TXT_FIND_PLACES,EXTRA_PARAMS,FULL_PARAMS);
}

// Called from the page
function InstallACBasic(frm, fld, sb, pn, rl, img, sf, scale, hideFull){
	if(txtbox != fld && imgAnimation){ imgAnimation.style.display = 'none'; }
	form = frm;
	txtbox = fld;
	iatabox = sb;
	url = pn;
	if(!rl){ rl = 'en'; }
	locale = urlEncodeString(rl);
	imgAnimation = img;
	if(scale){ ExtraWidth = scale; }
	submitFunction = sf;
	hideFullSearch = hideFull;
	setupSuggest();
}

function InstallAC(frm, fld, sb, pn, rl, img, sf, scale){
	InstallACBasic(frm, fld, sb, pn, rl, img, sf, scale, false)
}

var commonItems = null;
function AddCommon(arr){
	if(!commonItems)
		commonItems = new Array();

	commonItems.push(arr);
}

// handles document keydown
function keydown(event){
	if(!event && window.event){
		event = window.event;
	}
	if(event){
		lastKeyCode = event.keyCode;
	}
}

function resize(){
	setPopupDimensions();
}

function setPopupDimensions(){
	try{
		if(popup){
			popup.style.left = getPopupLeft(txtbox) + 'px';
			popup.style.top = getPopupTop(txtbox) + txtbox.offsetHeight - 1 + 'px';
			popup.style.width = getPopupWidth() + 'px'

			if(popup.hideFrame){
				popup.hideFrame.style.left = popup.style.left;
				popup.hideFrame.style.top = popup.style.top;
				popup.hideFrame.style.width = popup.style.width;
			}
		}
	}
	catch(ex){}
}

function getPopupWidth(){
	return (txtbox.offsetWidth) * ExtraWidth;
}

function setupSuggest(){
	if(GetHttpObject()){ hasXml = true; }
	else{ hasXml = false; }

	fullUrl = '' + url + '?hl=' + locale;

	form.onsubmit = function(){ return false; };
	txtbox.autocomplete = 'off';
	txtbox.onblur = textboxBlur;

	if(txtbox.createTextRange){ txtbox.onkeyup = new Function('return keyup(event);'); }
	else{ txtbox.onkeyup = keyup; }

	txtbox.onsubmit = closeSuggest;
	text = txtbox.value;
	lastVal = text;
	cacheResult('', 0, new Array(), new Array(), new Array());

	if(!popup){createPopup();}

	window.onresize = resize;
	document.onkeydown = keydown;
}

function createPopup(){
	popup = document.createElement('DIV');
	popup.id = 'completeDiv';
	popup.className = boxClass;
	popup.style.zIndex = '100';
	popup.style.position = 'absolute';
	popup.style.display = 'none';
	setPopupDimensions();
	document.body.appendChild(popup);

	if(!popup.hideFrame && BrowserNeedIFrame()){
		// IFRAME to hide dropdown lists
		hideFrame = document.createElement('IFRAME');
		hideFrame.id = 'hideFrame';
		hideFrame.style.border = '0px';
		hideFrame.style.zIndex = '99';
		hideFrame.style.position = 'absolute';
		hideFrame.style.display = 'none';
		setPopupDimensions();
		document.body.appendChild(hideFrame);
		popup.hideFrame = hideFrame;
	}
}

function clearPopup(){
	if(popup){
		popup.innerHTML = '';
		setPopupDimensions();
	}
}

// Hide the drop down box
function hideSuggest(){
	isVisible = false;
	var box = GetItemById('completeDiv');
	if(box){
		box.style.display = 'none';
		if(box.hideFrame)
			box.hideFrame.style.display = 'none';
	}
}

// Show the drop down box
function showSuggest(){
	if(!isVisible){
		isVisible = true;
		var box = GetItemById('completeDiv');
		if(box){
			setPopupDimensions();
			box.style.display = '';
			if(box.hideFrame)
				box.hideFrame.style.display = '';
		}
	}
}

// textbox onblur
function textboxBlur(event){
	if(!event && window.event){ event = window.event; }
	bCheckInput = false;
	abortSuggest();
	hideSuggest();
	if(lastKeyCode == 9){ // TAB
		lastKeyCode = -1;
	}
}

// this is called onKeyup of the textbox
function keyup(e){
	bCheckInput = true;
	setTimeout('checkInput()', 100);
	currentKeyCode = e.keyCode;
	processKeyUp(currentKeyCode);
}

function focusTextbox(){
	txtbox.focus();
}

function getItemText(itm){
	if(!itm){ return null; }
	if(itm.displayString){
		var value = itm.displayString;
		if(itm.displayString == '&nbsp;'){ return ''; }
		else{ return itm.displayString; }
	}
	else{ return ''; }
}

function getItemValue(itm){
	if(!itm){ return null; }
	if(itm.valueString){ return itm.valueString; }
	else{ return ''; }
}

// Save a result to the cache object
function cacheResult(itemKey, type, itemNames, itemValues, itemTypes){
	var newItem = new Object();
	newItem.type = type;
	newItem.names = itemNames;
	newItem.values = itemValues;
	newItem.types = itemTypes;
	itemKey = itemKey.toLowerCase();
	cache[itemKey] = newItem;
}

function sendRPCDone(itemkey, searchType, itemStrings, itemValues, itemTypes){
	if(activeCalls > 0)
		activeCalls--;

	cacheResult(itemkey, searchType, itemStrings, itemValues, itemTypes); // cache the result

	popup.displayStrings = itemStrings;	// City
	popup.valueStrings = itemValues;	// IATA
	popup.typeStrings = itemTypes;		// Airport flag

	// render drop down
	render(popup, popup.displayStrings, popup.valueStrings, popup.typeStrings);
	getSuggestRows(popup);
	if(popup.displayStrings.length > 0){
		popup.height = (popup.offsetHeight ? popup.offsetHeight : popup.style.pixelHeight);
		if(popup.hideFrame){ popup.hideFrame.height = popup.height; }
	} else{
		hideSuggest();
	}
}

// Called when a key is pressed
function processKeyUp(keyCode){
	var origText = text;
	text = txtbox.value;
	if(navigateList(keyCode) && keyCode != 0){
		if(text.indexOf(origText) != 0){clearPopup();}
		if(iatabox){ iatabox.value = ''; }
		isKeyPressed = true;
		getSuggestRows(popup);
	}
}

// used close the suggest
function closeSuggest(){
	closing = true;
	hideSuggest();
	return false;
}

function urlEncodeString(val){
	if(encodeURIComponent){
		return encodeURIComponent(val);
	}
	if(escape){
		return escape(val)
	}
}

// Calculates the time to wait before checking if the text has changed
function getCallbackTime(num){
	var t = 100;
	for(var i = 1; i <= (num-2)/2; i++){
		t = t*2;
	}
	t = t+50;
	return t;
}

function getCommonItems(val){
	if(!commonItems)
		return null;

	var names = new Array();
	var iatas = new Array();
	var flags = new Array();
	var commonItem = null;
	var thisVal = val.toLowerCase();

	for(var i = 0; i < commonItems.length; i++){
		var thisName = commonItems[i][0].toString().substring(0, val.length).toLowerCase();
		var thisIATA = commonItems[i][1].toString().toLowerCase();
		if(thisName == thisVal || thisIATA == thisVal){
			names.push(commonItems[i][0]);
			iatas.push(commonItems[i][1]);
			flags.push(commonItems[i][2]);

			commonItem = new Object();
			commonItem.type = 0;
			commonItem.names = names;
			commonItem.values = iatas;
			commonItem.types = flags;
		}
	}
	return commonItem;
}

// this function is polled every 100 milliseconds
// once the text changes and the length exceeds three
// then make a call to the server.
function checkInput(){
	if(isMorePressed || (isKeyPressed && lastVal != text && text.length > 2)){
		if(!closing){
			var searchKey = text.toLowerCase();
			var searchText = urlEncodeString(searchKey);
			var cacheItem = (isMorePressed ? null : cache[searchKey]);
			if(!isMorePressed && !cacheItem)
				cacheItem = getCommonItems(text);

			var isValidCache = (!isMorePressed && cacheItem && cacheItem.type == (fullSearch ? 1 : 0));
			if(isValidCache){
				// cached data found so use that
				abortSuggest();
				sendRPCDone(text, cacheItem.type, cacheItem.names, cacheItem.values, cacheItem.types);
			}
			else{
				 // no cache found, make remote call
				activeCalls++;
				if(hasXml){ doQuery(searchText); }
			}
			txtbox.focus()
			txtbox.value = txtbox.value;
		}
		isMorePressed = false;
		closing = false;
	}
	lastVal = text;
	isKeyPressed = false;
	if(bCheckInput){ setTimeout('checkInput()', getCallbackTime(activeCalls)); }
	return true
};

// Called on mousedown of the div
function itemClick(){
	abortSuggest();
	text = getItemText(this);
	setTextbox(text);
	setIata(getItemValue(this));
	closing = true;
	closeSuggest();
};

// Called on mousedown of the more places div
function moreItemClick(){
	abortSuggest();
	if(imgAnimation){imgAnimation.style.display = '';}
	strings.extraparams = strings.fullparams.replace('&amp;','&');
	fullSearch = true;
	isMorePressed = true;
}

// called on mouse over the div
function itemRollover(){
	if(currentItem){
		currentItem.className = (currentItem.offCss ? currentItem.offCss : itemClass);
	}
	this.className = (this.onCss ? this.onCss : itemOverClass);
}

// called on mouseout of the div
function itemRollout(){
	this.className = (this.offCss ? this.offCss : itemClass);
}

//handles moving up and down
function setCurrentItem(index,step){
	if(!suggestRows || rowCount <= 0)
		return;

	index += step;
	if(index >= rowCount){ index = rowCount - 1; }
	if(currentIndex != -1 && index != currentIndex){ currentIndex = -1; }

	if(index < 0){
		currentIndex = -1;
		text = currentText;
		setTextbox(currentText);
		setIata('');
		if(currentItem){ currentItem.className = currentItem.offCss; }
		return;
	}
	
	if(suggestRows[index].itemType == 3){
		if(rowCount > index+1){ setCurrentItem(index,step); }
		else{ currentIndex = -1; }
		return;
	}

	currentIndex = index;

	if(currentItem){ currentItem.className = currentItem.offCss; }
	currentItem = suggestRows[index];
	if(currentItem){ currentItem.className = currentItem.onCss; }

	showSuggest();

	if(currentItem.itemType < 3){
		text = currentText;
		setTextbox(getItemText(currentItem))
		setIata(getItemValue(currentItem));
	}
	else{
		text = currentText;
		setTextbox(currentText);
		setIata('');
	}
}

//handles UP + DOWN Keys
function navigateList(keyCode){
	if(keyCode == 40){ // down key
		if(isVisible){ setCurrentItem(currentIndex,1); }
		else if(rowCount > 0){ showSuggest(); }
		return false;
	}else if(keyCode == 38){ // up key
		if(isVisible){ setCurrentItem(currentIndex,-1); }
		else if(rowCount > 0){ showSuggest(); }
		return false;
	}else if(keyCode == 13 || keyCode == 3){ // enter
		if(currentItem && currentItem.itemType == 4 && currentItem.func){ currentItem.func(); }
		else if(isVisible){ closeSuggest(); }
		else if(submitFunction){ UnInstall(); submitFunction(); }
		return false;
	}
	return true;
}

function getSuggestRows(pop){
	suggestRows = getSuggestItems(pop);
	rowCount = suggestRows.length;
	currentText = text;

	if(text == '' || rowCount == 0){ hideSuggest(); }
	else{ showSuggest(); }

	currentIndex = -1;
	currentItem = null;
}

function getPopupLeft(elem){
	return getPopupOffset(elem, 'offsetLeft');
}

function getPopupTop(elem){
	return getPopupOffset(elem, 'offsetTop');
}

function getPopupOffset(elem, prop){
	var val = 0;
	while(elem){
		var doAdd = true;
		if(elem.currentStyle && elem.currentStyle.position == "absolute"){ doAdd = false; }
		if(doAdd){ val += elem[prop]; }
		elem = elem.offsetParent;
	}
	return val;
}

// populates the div with headers and options
function render(itm, itemStrings, itemValues, itemTypes){
	while(itm.childNodes.length > 0){itm.removeChild(itm.childNodes[0]);}
	var header1Shown = false;
	var header2Shown = false;
	if(itemStrings.length == 0){
		itemStrings.push(strings.noairports);
		itemValues.push('');
		itemTypes.push(3);
	}
	var maxRows = (typeof MAX_ROWS != 'undefined' ? MAX_ROWS : 20);
	for(var f = 0; f < itemStrings.length && f < maxRows; ++f){
		if(!header1Shown && (itemTypes[f] == 1 || itemTypes[f] == 3)){
			header1Shown = true;
			var header = document.createElement('DIV');
			header.innerHTML = '<B>' + strings.topsection + '</B>';
			header.className = headerClass;
			itm.appendChild(header);
		}
		if(!header2Shown && itemTypes[f] == 0){
			header2Shown = true;
			var header = document.createElement('DIV');
			header.innerHTML = '<B>' + strings.bottomsection + '</B>';
			header.className = headerClass;
			itm.appendChild(header);
		}

		var click = (itemTypes[f] != 3 ? itemClick : null);
		var hover = (itemTypes[f] != 3 ? itemOverClass : itemClass);
		itemDiv = createItem(itemStrings[f],itemValues[f],itemTypes[f],itemClass,hover,click);
		itm.appendChild(itemDiv);
	}
	if(!fullSearch && !hideFullSearch){
		var itemDiv = createItem(strings.findplaces,'',4,moreClass,itemOverClass,moreItemClick);
		itm.appendChild(itemDiv);
	}
}

function createItem(txt,val,type,offCss,onCss,click){
	var itemDiv = document.createElement('DIV');
	itemDiv.className = offCss;
	itemDiv.style.overflow = 'hidden';
	itemDiv.displayString = txt;
	itemDiv.valueString = (type == 1 ? val : null);
	itemDiv.itemType = type;
	itemDiv.onCss = onCss;
	itemDiv.offCss = offCss;
	itemDiv.func = click;

	itemDiv.onmousedown = click;
	itemDiv.onmouseover = itemRollover;
	itemDiv.onmouseout = itemRollout;

	if(val && val.length > 0){
		var displaySpan = document.createElement('SPAN');
		displaySpan.style.width = '86%';
		displaySpan.style.cssFloat = 'left';
		displaySpan.style.display = 'inline-block';
		displaySpan.innerHTML = txt;

		var valueSpan = document.createElement('SPAN');
		valueSpan.className = valueClass;
		valueSpan.style.width = '12%';
		valueSpan.style.cssFloat = 'left';
		valueSpan.style.display = 'inline-block';
		valueSpan.innerHTML = val;

		itemDiv.appendChild(displaySpan);
		itemDiv.appendChild(valueSpan);
	}
	else{
		itemDiv.innerHTML = txt;
	}
	return itemDiv;
}

// gets a reference to the xml http object
function GetHttpObject(){
	var obj = null;
	if(window.XMLHttpRequest){
		obj = new XMLHttpRequest();
	}
	else if(window.ActiveXObject){
		try{ obj = new ActiveXObject('Msxml2.XMLHTTP'); }
		catch(e){
			try{ obj = new ActiveXObject('Microsoft.XMLHTTP'); }
			catch(oc){ obj = null; }
		}
	}
	return obj;
}

// make a request to the server
function doQuery(val){
	abortSuggest();
	req = GetHttpObject();
	if(req){
		if(imgAnimation){imgAnimation.style.display = '';}
		req.open('GET', fullUrl + strings.extraparams + '&js=true&qu=' + val, true);
		req.onreadystatechange = function(){
			try{
				if(req.readyState == 4){
					if(imgAnimation){imgAnimation.style.display = 'none';}

					if(!req.responseText || req.responseText.charAt(0) == '<'){
						activeCalls--;
					}
					else{
						showSuggest();
						eval(req.responseText);
					}
				}
			}
			catch(ex){}
		};
		req.send(null);
	}
}

function abortSuggest(){
	if(req && req.readyState != 0){
		req.abort();
		req = null;
		if(imgAnimation){imgAnimation.style.display = 'none';}
	}
}

function setTextbox(val){
	lastVal = val;
	if(txtbox){ txtbox.value = val; }
}

function setIata(val){
	if(iatabox){ iatabox.value = val; }
}

function getSuggestItems(pop){
	var tempRows = new Array();
	arr = pop.getElementsByTagName(itemTagName);
	for(var i = 0; i < arr.length; i++){
		if(arr[i].displayString != null)
			tempRows.push(arr[i]);
	}
	return tempRows;
}

function BrowserNeedIFrame(){
	var agent = navigator.userAgent;
	var arrNoFrame = ['Konqueror'];
	for(var i = 0; i < arrNoFrame.length; i++){
		if(agent.indexOf(arrNoFrame[i]) != -1){ return false;}
	}
	return true;
}

function GetItemById(id){
	return (document.all ? document.all[id] : document.getElementById(id));
}
