//Objects

var sobj = null;
var maxresults = 10;
var smonitor = new Array();
var samplefreq = 500;
var debugme = false;
var fieldsense = 3; //Only start working after 3 or more characters are typed in the field.
var rpcfail = 2000; //number of milliseconds to assume that the rpc has failed - unblock the search and let it try again.
var autoc_div = new Array();
var xmlhttpObj = null;
var URLPREFIX = s_appPath+"/Lookup.aspx?";

var NORESULTS_MESSAGE = 'Sorry, no results for this search';

function searchObj ()
{
	this.rsets = new Array();
	this.add = function () {
		this.rsets['#'+arguments[0]].results['#'+arguments[1]] = new resultObj(arguments[1], arguments[2], arguments[3]);
	}
	this.get = function (key) {
		return this.rsets['#'+key];
	};
};

function resultsObj (partsearch)
{
	this.partsearch = new String(partsearch);
	this.results = new Array();
	this.length = null;
	this.timestamp = new Date();
	this.timestamp = this.timestamp.getTime();
	this.state = false; // false means that this object isn't populated with results from the server, true means it does
	
	this.getLength = function () {
		var count = 0;
		for (elem in this.results) count++;
		this.length = count;
		return count;
	};
	
	this.display = resultsObj_display;
};

function resultsObj_display(fieldname, currpartsearch)
{
//	debugs(currpartsearch+' != '+autoc_div[fieldname]); 
	if (''+currpartsearch != ''+autoc_div[fieldname])
	{
//		debugs('create new div');
		autoc_div[fieldname] = currpartsearch;
		var field = document.getElementById(fieldname);
		var encdiv = document.getElementById(fieldname+'_container');
		if ((field != null) || (encdiv != null))
		{
			var ndiv = document.createElement("div");
			if (browser.isIE == true) {
				ndiv.setAttribute('className','autocdiv');
			} else {
				ndiv.setAttribute('class','autocdiv');
			};
			ndiv.setAttribute('id','autoc_'+fieldname);
			var ulobj = document.createElement("ul");
			var liobj = null; var textobj = null; var ancobj = null; var cmd = null;
			var reslength = this.getLength();
			if (reslength > 0)
			{
				for (i in this.results)
				{
					liobj = document.createElement("li");
					liobj.setAttribute('id',fieldname+"__"+this.results[i].icao);
					ancobj = document.createElement("a");
					ancobj.setAttribute('href','#');
					cmd = "ancobj.onmousedown = function () { setField('"+fieldname+"', '"+this.results[i].icao+"') }";
					eval(cmd);
					textobj = document.createTextNode(this.results[i].dispname+' ['+this.results[i].icao+']');
					ancobj.appendChild(textobj);
					liobj.appendChild(ancobj);
					ulobj.appendChild(liobj);			
				};
			} else {
				liobj = document.createElement("li");
				ancobj = document.createElement("a");
				ancobj.setAttribute('href','#');
				textobj = document.createTextNode(NORESULTS_MESSAGE);
				ancobj.appendChild(textobj);
				liobj.appendChild(ancobj);
				ulobj.appendChild(liobj);
				notfoundField(fieldname);
			};
			ndiv.appendChild(ulobj);
			var existnode = document.getElementById('autoc_'+fieldname);
			if (existnode != null)
			{
				encdiv.replaceChild(ndiv,existnode);
			} else {
				var node = null;
				var foundnode = false;
				for (var i = 0; i < encdiv.childNodes.length; i++)
				{
					node = encdiv.childNodes[i];
					if (node.id == ('autoc_'+fieldname))
					{
						//We've found the node, so we shall replace it with the new one
						foundnode = true;
						encdiv.replaceChild(ndiv,node);
						continue;
					};
				};
				if (!foundnode)
				{
					//Doesn't exist, so add a new one...
					encdiv.appendChild(ndiv);
				};
			}
			showAutoComplete(fieldname);
			debugs2(encdiv.innerHTML);
		};
	};
};

function setField(fieldname, val)
{
	var field = document.getElementById(fieldname);
	if (field != null) field.value = val;
};

function getRealPos(i,which) 
{
	iPos = 0;
	while (i!=null) {
		iPos += i["offset" + which]
		i = i.offsetParent
	};
	return iPos
};

function showAutoComplete(fieldname)
{
	var field = document.getElementById(fieldname);
	var autoc = document.getElementById('autoc_'+fieldname);
	if ( (field != null) && (autoc != null) )
	{
		if (''+autoc.className == 'autocdiv')
		{
			autoc.style.pixelLeft = getRealPos(field,'Left');
			autoc.style.pixelTop = getRealPos(field,'Top')+field.offsetHeight;
			autoc.className = 'autocdiv_visible';
			autoc.style.display = 'block';
		};
		if (document.all)
		{
			hideIEBugFields();
		};
	};
	normalField(fieldname);
};

function hideAutoComplete(fieldname)
{
	var autoc = document.getElementById('autoc_'+fieldname);
	if (autoc != null)
	{
		autoc.style.display = 'none';
		if (document.all)
		{
			showIEBugFields();
		};
	};
};

function hideIEBugFields() { visIEBugFields('hidden') };
function showIEBugFields() { visIEBugFields('visible') };

function visIEBugFields(visval)
{
	var tgs = document.getElementsByTagName('select');
	var tgttg = null;
	for (var i = 0; i < tgs.length; i++) 
	{
		tgttg = tgs[i];
		if (tgttg != null) tgttg.style.visibility = visval;
	};
};

function resultObj ( icao, dispname, availflights )
{
	this.icao = icao;
	this.dispname = dispname;
	this.availflights = availflights;
};

function s0 ()
{
	var arglength = arguments.length;
	if (arglength > 0)
	{
		var partsearch = arguments[0];
		if (sobj == null) { sobj = new searchObj() };
		if (sobj.rsets['#'+partsearch] == null) { sobj.rsets['#'+partsearch] = new resultsObj(partsearch) };
		if (arglength > 1)
		{	
			//Plus one here as there is an initial param that we ignore...
			if (arglength > (maxresults+1)) { arglength = maxresults+1 }; 
			for (var i = 1; i < arglength; i++)
			{
				cmdstr = 'sobj.add("'+partsearch+'", "'+arguments[i][0]+'", "'+arguments[i][1]+'", "'+arguments[i][2]+'")';
				debugs(cmdstr);
				eval(cmdstr);
			};
			sobj.rsets['#'+partsearch].state = true;
		} else {
			sobj.rsets['#'+partsearch].state = true;
		}
	};
};

var throbid = null;
function throbField(fieldobj) { 
	fieldobj.className = 'jtx_textfield_throb';  
	if (throbid == null) {
		throbid = setTimeout('normalField("'+fieldobj.id+'")', 5000)
	};
};
function notfoundField(fieldname) {
	if (throbid!= null) { 
		clearTimeout(throbid); 
		throbid = null 
	}; 
	var fieldobj = document.getElementById(fieldname); 
	fieldobj.className = 'jtx_textfield_notfound';
	throbid = setTimeout('normalField("'+fieldname+'")', 5000)	
};
function normalField(fieldname) { 
	if (throbid!= null) { 
		clearTimeout(throbid); 
		throbid = null 
	}; 
	var fieldobj = document.getElementById(fieldname); 
	fieldobj.className = 'jtx_textfield';
};

function monitorObj (fieldname, state)
{
	this.fieldname = fieldname;
	this.field = document.getElementById(fieldname);
	this.state = state;
	this.intervalid = null;
	this.isbound = false;
	this.lastknowntext = this.field.value;
	this.divid = null;
	this.selectedindex = null;
	
	this.gocomplete = function () {
		if ( (sobj == null) 
			|| (sobj.rsets['#'+this.lastknowntext] == null)
			|| (sobj.rsets['#'+this.lastknowntext].state == false) )
		{
			//go find some results
			throbField(this.field);
			debugs('gocomplete : go get results - '+this.lastknowntext);
			sendRPC(this.lastknowntext);
		} else {
			//we found them so display them
			debugs('gocomplete : results present - '+this.lastknowntext);
			sobj.rsets['#'+this.lastknowntext].display(this.fieldname, this.lastknowntext)
		};
	};
	
	this.handleKeys = monitorObj_handleKeys;		
	this.keycontrol = monitorObj_keycontrol;
};

function monitorSearch (fieldname)
{
	if (smonitor['#'+fieldname] == null)
	{
		smonitor['#'+fieldname] = new monitorObj(fieldname, false);
	};
	if (smonitor['#'+fieldname].intervalid == null)
	{
		smonitor['#'+fieldname].intervalid = setInterval('checkfield("'+fieldname+'")',samplefreq);
	};
	if (boundfields['#'+fieldname] != true)
	{
		bindKeys(fieldname);
		if (boundfields['#'+fieldname] == true) { smonitor['#'+fieldname].isbound = true };
	};
};

function endSearch (fieldname)
{
	if (smonitor['#'+fieldname] != null)
	{
		clearInterval(smonitor['#'+fieldname].intervalid);
		smonitor['#'+fieldname].intervalid = null;
		hideAutoComplete(fieldname);
		autoc_div[fieldname] = null;
	};
};

function checkfield(fieldname)
{
	//debugs('checkfield("'+fieldname+'")');
	with (smonitor['#'+fieldname])
	{
		var newval = new String(field.value);
		var oldval = new String(lastknowntext);
		lastknowntext = newval;
		if ((newval != oldval) && (newval.length >= fieldsense) ) { gocomplete() };
	};
	//setTimeout('dumpObj("sobj",sobj)',0);
};

function debugs(str)
{
	if (debugme)
	{
		var obj = document.getElementById('debugme');
		obj.value = str + "\n" + obj.value;
	};
};

function debugs2(str)
{
	if (debugme)
	{
		var obj = document.getElementById('debugme2');
		obj.value = str;
	};
};

function sendRPC(partsearch)
{
	debugs('sendRPC("'+partsearch+'")');
	if ( (sobj != null) && (sobj.rsets['#'+partsearch] != null) && (sobj.rsets['#'+partsearch].state == false) )
	{
		//If it's there, and the state is false... assume we have already requested it before so check the timestamps
		var origtime = sobj.rsets['#'+partsearch].timestamp;
		var currtime = new Date();
		currtime = currtime.getTime();
		if (currtime > (origtime+rpcfail))
		{
			//If the currtime is after the original timestamp + the time given for an rpcfail, then reset the rset and continue as if we've never requested
			//Even if the rpc comes back, the rset will be instantiated again anyway - so it won't cause it to fail.
			sobj.rsets['#'+partsearch] == null;
			debugs('RPC Failure sensed, requesting for this again: '+partsearch);
		};
	};

	if (sobj == null) { sobj = new searchObj() };
	if (sobj.rsets['#'+partsearch] == null) {	sobj.rsets['#'+partsearch] = new resultsObj(partsearch) };

	debugs('callAzure("'+partsearch+'")');
	callAzure(partsearch);
};


function callAzure(ps)
{
	if ( (xmlhttpObj) && (xmlhttpObj.readyState != 0) )
	{
		xmlhttpObj.abort();
	};
	if (xmlhttpObj == null)
	{
		getXMLHTTP();
	};
	if (xmlhttpObj)
	{
		xmlhttpObj.open("GET",URLPREFIX+"ps="+ps,true);
		xmlhttpObj.onreadystatechange = function() 
		{
			debugs('onreadystatechanged');
			if ( (xmlhttpObj.readyState == 4) && (xmlhttpObj.responseText) )
			{
				if (xmlhttpObj.responseText.charAt(0) == "<") {
					_timeoutAdjustment--
				} else {
					debugs('responseText:'+xmlhttpObj.responseText);
					eval(xmlhttpObj.responseText)
				};
			};
		};
	};
	xmlhttpObj.send(null)
};

function getXMLHTTP()
{
	try {
		xmlhttpObj = new ActiveXObject("Msxml2.XMLHTTP");
	} catch(e) {
		try {
			xmlhttpObj = new ActiveXObject("Microsoft.XMLHTTP");
		} catch(e2) {
			xmlhttpObj = null;
		};
	};
	if(!xmlhttpObj && typeof XMLHttpRequest != "undefined") 
	{
		xmlhttpObj = new XMLHttpRequest()
	};
	if (xmlhttpObj != null) { return true };
	return null;
};


// Determine browser and version.

function Browser() {
// blah, browser detect, but mouse-position stuff doesn't work any other way
  var ua, s, i;

  this.isIE    = false;
  this.isNS    = false;
  this.version = null;

  ua = navigator.userAgent;

  s = "MSIE";
  if ((i = ua.indexOf(s)) >= 0) {
    this.isIE = true;
    this.version = parseFloat(ua.substr(i + s.length));
    return;
  }

  s = "Netscape6/";
  if ((i = ua.indexOf(s)) >= 0) {
    this.isNS = true;
    this.version = parseFloat(ua.substr(i + s.length));
    return;
  }

  // Treat any other "Gecko" browser as NS 6.1.

  s = "Gecko";
  if ((i = ua.indexOf(s)) >= 0) {
    this.isNS = true;
    this.version = 6.1;
    return;
  }
}

var browser = new Browser();

//Bind the keys for accelerated selection of airport...

var boundfields = new Array();

function bindKeys(fieldname) 
{
	if (document.getElementById)
	{
		var fobj = document.getElementById(fieldname);
		if (fobj != null)
		{
			boundfields['#'+fieldname] = true;
			if (document.all)
			{
				document.onkeydown = filterKeys;
				document.onkeyup = filterKeys;
			} else {
				fobj.onkeydown = filterKeys;
				fobj.onkeyup = filterKeys;
			}
		};
	}
};
function filterKeys(e)
{
	if (!e) e = window.event;
	var objid = null;
	if (e.srcElement)
	{
		objid = '' + e.srcElement.id;
	} else if (e.target) {
		objid = '' + e.target.id;
	};
	if (objid != null)
	{
		if (boundfields['#'+objid] == true)
		{
			smonitor['#'+objid].handleKeys(e);
		};
	};
};

function monitorObj_handleKeys(e)
{
	// if acdiv visible
	// and if there are results displayed
	// then handle up/down and select on keyboard
	var cancelme = false;
	var cmdstr = "";
	switch (e.keyCode)
	{
		case 40:
			cmdstr = "keycontrol('down', '"+this.fieldname+"');";
			cancelme = true;
			break;
		case 38:
			cmdstr = "keycontrol('up', '"+this.fieldname+"');";
			cancelme = true;
			break;
		case 13:
			cmdstr = "keycontrol('select', '"+this.fieldname+"');";
			cancelme = true;
			break;
	};
	if (cancelme == true)
	{
		if (e.cancelBubble != null)
		{
			e.returnValue = false;
			e.cancelBubble = false;
		} else {
			e.preventDefault();
			e.stopPropagation();
		};
		setTimeout(cmdstr,0); //Handle the key event in a spun thread, for speed reasons.
	};
};

function keycontrol(action, fieldname)
{
	smonitor['#'+fieldname].keycontrol(action);
};

function monitorObj_keycontrol(action)
{
	var autoc = document.getElementById('autoc_'+this.fieldname);
	if (autoc != null) 
	{
		if (''+autoc.className == 'autocdiv_visible')
		{
			if ((sobj.rsets['#'+this.lastknowntext] != null) && (sobj.rsets['#'+this.lastknowntext].length > 0))
			{
//				alert(action); //working!
			};
		} else {
			this.selectedIndex = null;
		};
	};
	
};

function globalSearchInit()
{
};

appendLoad(globalSearchInit);

/* reference... delete...

		case 9:
			alert('select: tab');
			cancelme = true;
			break;


	
	return true;

	var keyInfo = String.fromCharCode(e.keyCode) + '\n';
	keyInfo += 'Event: ' + e.type + '\n\n';
	keyInfo += 'You pressed: ' + String.fromCharCode(e['keyCode']) + ' [Decimal: ' + e['keyCode'] + ']\n';
	keyInfo += 'ALT: ' + e['altKey'] + '\n';
	keyInfo += 'CTRL: ' + e['ctrlKey'] + '\n';
	keyInfo += 'SHIFT: ' + e['shiftKey'] + '\n';
	keyInfo += 'REPEAT: ' + e['repeat'] + '\n';
	keyInfo += 'WHICH: ' + e['which'] + '\n';
	if (e.srcElement)
	{
		keyInfo += 'SRC (IE): '+ e.srcElement.id;
	} else {
		keyInfo += 'TARGET (other): '+ e.target.id;
	};
	alert(keyInfo);

*/