var http_request;
var flexibleCountry = "HK,CN,BD,VN,PH,TH,NP,TW,IN,KR,MY,KH";
var nonInfantPort = "HKG,HKT";
var hideAirportCodePort = "TYO";//added by cppzop for pax.0455
var airportsOfPortCode = new Object(); // added by cpphowc for pax.0455, when there is port code, also search their airport codes, TYO -> HND, NRT
airportsOfPortCode['TYO'] = ['HND', 'NRT']; // added by cpphowc for pax.0455

function getAbsLeft(obj){
	var	l=obj.offsetLeft;
	while(obj=obj.offsetParent)
		l+=obj.offsetLeft;
	return l;
}

function getAbsTop(obj){
	var	t=obj.offsetTop;
	while(obj=obj.offsetParent)
		t+=obj.offsetTop;
	return	t;
}

function changeBkgrnd(obj){
	addClassName(obj, "selected");
}

function changeBkgrnd_Blur(obj){
	removeClassName(obj, "selected");
}

function addClassName(element, className) {
 	if (!Element.hasClassName(element, className)) element.className = (element.className+' '+className);
 }

function removeClassName(element, className) {
 	if (Element.hasClassName(element, className)) element.className = element.className.replace(className, '');
}

/*
 * this is a cache to hold flight data items so that we don't have to create them everytime
 */
var FlightDataCache = Class.create();
Object.extend(FlightDataCache.prototype, {
  initialize : function () {
  	this.flightDataCacheArray = new Object();
  },
  getFlightDataItem : function (dataContainer, from, to) {
	var itemFrom = this.flightDataCacheArray[from];
	if (itemFrom == null) {
		itemFrom = new Object();
		this.flightDataCacheArray[from] = itemFrom;
	}
  	var item = itemFrom[to];
	if (item == null) {
		item = new FlightData(dataContainer, from, to);
		itemFrom[to] = item;
	}
	
	return item;
  }
}
);

// initialise as a singleton
var FlightDataCache = new FlightDataCache();

/*
 * this object holds data for a flight combination, eg SYD-MEL
 * it uses a data container which holds all the information relevant to 
 * this airport pair combination.
 * 
 * This object can be queried for valid flights, valid classes and can be 
 * extended to hold further information by adding convenience methods and 
 * adding to the data matrix within the data container
 */
var FlightData = Class.create();
FlightData.prototype = {
  initialize : function (dataContainer, from, to) {
  	this.dataContainer = dataContainer;
  	this.airports = dataContainer.getAirports();
  	//this.fromAirports = dataContainer.getFromAirports();
  	//this.fromAirports = dataContainer.getToAirports();
  	//this.toAirports = dataContainer.getToAirports();
   	this.fromAirport = getObjectFromArrayByCode(from, this.airports);
   	this.toAirport = getObjectFromArrayByCode(to, this.airports);
   	//this.fromAirportIndex = indexOfAirportByCode(from, this.fromAirports);
   	//this.toAirportIndex = indexOfAirportByCode(to, this.toAirports);
	//this.matrixItem = getMatrixItem(this.fromAirportIndex,this.toAirportIndex,this.matrix, this.fromAirports.length, this.toAirports.length);
  },
  isValidFlight : function (evt) {
  	//if (this.matrixItem != null) {		
		// make assumption here that can't fly from and to the same city (SYD to SYD)
		if (this.fromAirport != this.toAirport) {
			//if (determineBooleanValueFromMatrixItem(this.matrixItem, this.dataContainer.getValidFlightIndex())) {
				return true;
			//}
		}
 // 	}
	return false;
  }  
}

/* 
 * this object holds the basic airport data for a airport
 */
var Airport = Class.create();
Airport.prototype = {
  initialize : function (code, airportName, countryCode, countries, portCode, ports) {
    this.code = code;
    this.airportName = airportName;
	this.country = getObjectFromArrayByCode(countryCode, countries);
	this.port = getObjectFromArrayByCode(portCode, ports);
  },
  getCountry : function () {
  	return this.country;
  },
  toStringNameOnly : function () {
  	//return this.port.portName;
	//CR463 - Adding airport name to the Booking O/D List

	//CR455 CPPHOWC - display HND/NRT instead of TYO for TYO
	var displayCode = null;
    if (this.code == 'TYO') {
		displayCode = 'HND/NRT';
    } else {
		displayCode = this.code;
	}

	return this.port.portName + ", (" + displayCode + ")";	
	//return this.port.portName + ", (" + this.code + ")"; // comment by CR455 CPPHOWC - display HND/NRT instead of TYO for TYO
  },
  toString : function () {
  	//return this.toStringNoCode() + " (" + this.code + ")";
	//CR463 - Adding airport name to the Booking O/D List
	//return this.port.portName + ", " + this.airportName + " (" + this.code + ")" + ", " + this.country.countryName;
	var codeStr = (hideAirportCodePort == this.code) ? ", " : " (" + this.code + "), ";//added by cppzop for pax.0455
	return this.port.portName + ", " + this.airportName + codeStr + this.country.countryName;
  },
  toStringAirportCodeOnly : function () {
  	//return this.toStringNoCode() + "<span class=\'aCode\'>" + " (" + this.code + ")" + "</span>";
  	//return this.port.portName + " (" + this.code + ")" + ", " + this.country.countryName;
	//CR463 - Adding airport name to the Booking O/D List
	//return this.port.portName + ", " + this.airportName + " (" + this.code + ")" + ", " + this.country.countryName;
	  return this.toString();//added by cppzop for pax.0455
  },
  toStringNoCode : function () {
  	return this.port.portName + ", " + this.country.countryName;
  },
  //CR#362 - Adjustment for the drop down list
  toStringCountryCode : function () {
  	return this.country.code;
  },
  // this assumes toString format of Airport, Country (AirportCode)
  toStringWithHighlightedAirport : function (highlightValue) {
  
	var airportText = this.toString();	
  	//var pattern = new RegExp("^" + highlightValue, "i");
	
	/*if (pattern.test(this.port.portName)) {
		var indexOfMatch = airportText.toLowerCase().indexOf(highlightValue.toLowerCase());
  	} else if (pattern.test(this.airportName)) {
		return airportText;
	} else if (pattern.test(this.country.countryName)) {
		var lengthOfPortName = this.port.portName.length;
		var indexAfterCountry = airportText.substring(lengthOfPortName).toLowerCase().indexOf(highlightValue.toLowerCase());
		indexOfMatch = lengthOfPortName + indexAfterCountry;
	} else {		
		var lengthOfStringNoCode = this.toStringNoCode().length;
		var indexAfterStringNoCode = airportText.substring(lengthOfStringNoCode).toLowerCase().indexOf(highlightValue.toLowerCase());
		indexOfMatch = lengthOfStringNoCode + indexAfterStringNoCode;		
	}*/
	
	//CR463 - Adding airport name to the Booking O/D List
	var pattern1 = new RegExp("^"+highlightValue, "i");
	var pattern2 = new RegExp("/"+highlightValue, "i");
	var pattern3 = new RegExp("[(]"+highlightValue, "i");
	var pattern4 = new RegExp(", "+highlightValue, "i");
	var indexOfMatch = -1;
	if (airportText.search(pattern1) != -1)
		indexOfMatch = airportText.toLowerCase().indexOf(highlightValue.toLowerCase());
	else
	if (airportText.search(pattern2) != -1) {
		indexOfMatch = airportText.toLowerCase().indexOf("/"+highlightValue.toLowerCase()) + 1;
	}
	else
	if (airportText.search(pattern3) != -1) {
		indexOfMatch = airportText.toLowerCase().indexOf("("+highlightValue.toLowerCase()) + 1;
	}
	else
	if (airportText.search(pattern4) != -1) {
		indexOfMatch = airportText.toLowerCase().indexOf(", "+highlightValue.toLowerCase()) + 2;
	}
	
	var beforeHighlight = airportText.substring(0, indexOfMatch);
	var highlighted = airportText.substring(indexOfMatch, indexOfMatch + highlightValue.length);
	var afterHighlight = airportText.substring(indexOfMatch + highlightValue.length,airportText.length);
	
	return beforeHighlight + "<b>" + highlighted + "</b>" +  afterHighlight;
  }
}

/**
 * this function takes a airport object and represents it as a hyperlinked String and highlights
 * the text entered to find it.
 */
function getAirportAsHTMLString(currentAirport, highlightValue, highlightMatch, isFound) {
	
	var anchor = "";
	var highlight = "";
	if (currentAirport.airportName.toLowerCase().indexOf(highlightValue.toLowerCase())==0) {
		anchor = "<font id=\"anchor\"></font>"
		if (currentAirport.airportName.toLowerCase()==(highlightValue.toLowerCase())) {
			//highlight=" class=\"toBoxHighlight\" ";
		}
	}
	var openingAnchorTag = anchor + "<a onFocus='changeBkgrnd(this)' onBlur='changeBkgrnd_Blur(this)' href='javascript:void(0)' id='to" + currentAirport.code + "'" + highlight + "/>";//imtcwc
	var airportText;
	if (highlightMatch) {
		airportText = currentAirport.toStringWithHighlightedAirport(highlightValue);
	} else {
		//CR#362 - Adjustment for the drop down list
		if (isFound == true) 
			airportText = "<div style=\"border-bottom: 1px dashed #000000; margin: 0; padding: 0 0 5px 0; line-height: 1em;\">" + currentAirport.toStringAirportCodeOnly() + "</div>";
		else
			airportText = currentAirport.toStringAirportCodeOnly();
	}
	var closingAnchorTag = "</a>";
	return openingAnchorTag + airportText + closingAnchorTag;
}

/* 
 * this object holds the basic data for a country
 */
var Port = Class.create();
Port.prototype = {
  initialize : function (code, portName) {
    this.code = code;
    this.portName = portName;
  }
}
  
/* 
 * this object holds the basic data for a country
 */
var Country = Class.create();
Country.prototype = {
  initialize : function (code, countryName) {
    this.code = code;
    this.countryName = countryName;
  }
}

/*
 * this object is the control object for the To text Box.
 * It sets up initial data and handles any expected events for the box.
 * 
 * Most importantly it handles the keyup event which will populate the available
 * to airports.
 */
var FromBoxControl = Class.create();
FromBoxControl.prototype = {
  initialize : function (fieldIndex, fromFieldId, fromBoxId, fromBoxListDivId, fromBoxPlusSign, fieldsToHide, dataContainer) {    
  	this.fieldIndex = $(fieldIndex);
    this.fromBox = $(fromBoxId);
    this.fromBoxListDiv = $(fromBoxListDivId);
    this.fromField = $(fromFieldId);
    this.fromBoxPlusSign = $(fromBoxPlusSign);
	this.currentSelection = "";
	this.fieldsToHide = fieldsToHide;	
	//this.dataContainer = dataContainer;	
	this.dataContainer = new DataContainer(dataContainer.myJSONObject);
	this.fromBox.onkeydown = this.fromBoxKeyDown.bindAsEventListener(this);
	this.fromBox.onkeyup = this.fromBoxKeyUp.bindAsEventListener(this);
	this.fromBox.onfocus = this.fromBoxFocus.bindAsEventListener(this);
	this.fromBoxPlusSign.onclick = this.fromBoxPlusSignClick.bindAsEventListener(this);
	this.boxOpen = false;
	this.inputType = 'textBox';	
	this.fromBoxPlusSignOptionList = null;
  },
  fromBoxKeyDown : function (evt) {

	if(evt != null && (evt.keyCode==40)){  // key down
		var predictiveTable = $("predictiveLookUp");		
		if(predictiveTable != null) {
			var anchorTags = predictiveTable.getElementsByTagName("a");
			if (this.currentSelection == "") {
				var firstItem = anchorTags[0];
				this.currentSelection = firstItem;
				changeBkgrnd(firstItem);
			} else {
				for (var i=0; i < anchorTags.length; i++) {
					if (Element.hasClassName(anchorTags[i], "selected")) {
						changeBkgrnd_Blur(anchorTags[i]);
						// if not the last item
						if (i < (anchorTags.length - 1)) {
							nextItem = anchorTags[i+1];
						// ie we are on the last item, go to first
						} else {
							nextItem = anchorTags[0];
						}
						this.currentSelection = nextItem;
						changeBkgrnd(nextItem);
						i = anchorTags.length;
					}
				}
			}
		}
		fixScrollPosition(this.fromBoxListDiv, this.currentSelection);
		return false;
	} else if(evt != null && evt.keyCode==38) {   // key up
		var predictiveTable = $("predictiveLookUp");
		if(predictiveTable != null) {
			var anchorTags = predictiveTable.getElementsByTagName("a");
			if (this.currentSelection != "") {
				for (var i=0; i < anchorTags.length; i++) {
					if (Element.hasClassName(anchorTags[i], "selected")) {
						changeBkgrnd_Blur(anchorTags[i]);
						// if not the last item
						if (i > 0) {
							nextItem = anchorTags[i-1];
						// on the first item, go to the last
						} else {
							nextItem = anchorTags[anchorTags.length - 1];
						}
						this.currentSelection = nextItem;
						changeBkgrnd(nextItem);
						i = anchorTags.length;
					}
				}
			// select last item
			} else {
				var lastItem = anchorTags[anchorTags.length - 1];
				this.currentSelection = lastItem;
				changeBkgrnd(lastItem);
			}
		}
		fixScrollPosition(this.fromBoxListDiv, this.currentSelection);
		return false;
	} else if(evt != null && evt.keyCode==13) {  // key enter				
		if (this.currentSelection != "") {
			this.currentSelection.onclick();
		} else {
			if (this.fromBoxListDiv.getElementsByTagName("a").length==1) {
				this.fromBoxListDiv.getElementsByTagName("a")[0].onclick();
			}
		}
	} else if (evt != null && evt.keyCode == 9) {
		if (this.currentSelection != "") {
			this.currentSelection.onclick();
		} else {
			this.fromBoxListDiv.getElementsByTagName("a")[0].onclick();
		}
	}
  },
  fromBoxKeyUp : function (evt) { 
	if(evt == null || evt.keyCode==40 || evt.keyCode==38 || evt.keyCode==13 || evt.keyCode==9 || evt.keyCode==37 || evt.keyCode==39 ) {  
	} else {
		if (this.fromBox.value == '') {						
			this.fromBox.value == '';
			this.fromField.value = '';	
		} else {
			this.currentSelection = "";			
	  		var oThis = this;
	  		if (this.dataContainer.toAirports == null) {
				http_request = getXmlHttpRequestObject();
				//CR#362 - Adjustment for the drop down list
				if (ajax_url.indexOf("?") < 0)
					http_request.open("GET", ajax_url+'?idx='+oThis.fieldIndex, true);
				else
					http_request.open("GET", ajax_url+'&idx='+oThis.fieldIndex, true);		
				http_request.onreadystatechange = function() {oThis.populateFromMatchingAirportsRequest(evt)}; 		
				http_request.send(null);
			} else {
				oThis.populateFromMatchingAirports(evt);
			}
  		}
	}
  },
  fromBoxFocus : function (evt) {
  	this.fromBox.select();
  	
  },
  fromBoxPlusSignClick : function (evt) {  	
 
  	if (this.boxOpen) {
		this.fromBoxListDiv.style.display='none';
		this.hideShowFields(false);
		this.setBoxOpen(false);
  	} else {
	  	this.fromBox.focus();
	  	var oThis = this;    	  	
	  	if (this.fromBoxPlusSignOptionList == null) {    
		  	http_request = getXmlHttpRequestObject();
			//CR#362 - Adjustment for the drop down list
			if (ajax_url.indexOf("?") < 0)
				http_request.open("GET", ajax_url+'?idx='+oThis.fieldIndex, true);	
			else
				http_request.open("GET", ajax_url+'&idx='+oThis.fieldIndex, true);	
			http_request.onreadystatechange = function() {oThis.populateFromAllAirports(evt)};
			http_request.send(null);
		} else {						
			var matchingAirports = getAirportsFromAirportCodes(this.dataContainer.getToAirports(), this.dataContainer.getAirports());
			var validAirports = getValidToAirports("", matchingAirports, this.dataContainer);
			this.populateFromOptions(evt, validAirports, this.fromBoxPlusSignOptionList, false);
			  	
			var predictiveTable = $("predictiveLookUp");
			var anchorTags = predictiveTable.getElementsByTagName("a");	
			for (var i=0; i < anchorTags.length; i++) {
				if (("to" + this.fromField.value) == anchorTags[i].id) {			
					this.currentSelection = anchorTags[i];
					changeBkgrnd(anchorTags[i]);
					fixScrollPosition(this.fromBoxListDiv,this.currentSelection);
				}
			}
		}
	}
  },
  populateFromAllAirports : function (evt) {  	
	if (http_request.readyState == 4) {
		if (http_request.status == 200) {
			this.dataContainer.toAirports = http_request.responseText.parseJSON();
			var matchingAirports = getAirportsFromAirportCodes(this.dataContainer.getToAirports(), this.dataContainer.getAirports());			
			var validAirports = getValidToAirports("", matchingAirports, this.dataContainer);
			
			var optionListStrC1="";
			var recordCount=0;
			
			//CR#362 - Adjustment for the drop down list
			var localIndex=-1;
			for (var x=0;x < validAirports.length-1; x++) {
				if (validAirports[x].toStringCountryCode().toUpperCase()==urlCountry.toUpperCase() && "GB"!=urlCountry.toUpperCase()) {
					localIndex = x;
					if ("CN"==urlCountry.toUpperCase()) {
						localIndex = 2;
						break;
					}
				} else
					break;
			}
			
			for (var x=0;x < validAirports.length; x++) {
				var currentAirport = validAirports[x];
				//CR#362 - Adjustment for the drop down list
				var isFound = false;
				if (x==localIndex)
					isFound = true;
				optionListStrC1=optionListStrC1+getAirportAsHTMLString(currentAirport, this.fromBox.value, false, isFound);
				recordCount++;
			}
			this.fromBoxPlusSignOptionList =
				"<table id=\"predictiveLookUp\">" + "<tr>" + 
				"<td valign=\"top\">" + optionListStrC1 + "</td>" +
				"</tr>" + "</table>";
			
		  	this.populateFromOptions(evt, validAirports, this.fromBoxPlusSignOptionList, false);
		  	
		  	var predictiveTable = $("predictiveLookUp");
			var anchorTags = predictiveTable.getElementsByTagName("a");	
			for (var i=0; i < anchorTags.length; i++) {
				if (("to" + this.fromField.value) == anchorTags[i].id) {			
					this.currentSelection = anchorTags[i];
					changeBkgrnd(anchorTags[i]);
					fixScrollPosition(this.fromBoxListDiv,this.currentSelection);
				}
			}
		}
	}
  },
  populateFromMatchingAirports : function (evt) {  	
	var matchingAirports = getAirportsThatMatchString(this.fromBox.value, this.dataContainer.getToAirports(), this.dataContainer.getAirports());  	
	var validAirports = getValidToAirports("", matchingAirports, this.dataContainer);
	
	var optionListStrC1="";
	var recordCount=0;
	for (var x=0;x < validAirports.length; x++) {
		var currentAirport = validAirports[x];
		optionListStrC1=optionListStrC1+getAirportAsHTMLString(currentAirport, this.fromBox.value, true, false);
		recordCount++;
	}
	optionList =
		"<table id=\"predictiveLookUp\">" + "<tr>" + 
		"<td valign=\"top\">" + optionListStrC1 + "</td>" +
		"</tr>" + "</table>";
	
	this.populateFromOptions(evt, validAirports, optionList, true);
  },
  populateFromMatchingAirportsRequest : function (evt) {
	if (http_request.readyState == 4) {
		if (http_request.status == 200) {
			this.dataContainer.toAirports = http_request.responseText.parseJSON();
			this.populateFromMatchingAirports(evt);
		}
	}
  },
  populateFromOptions : function (evt, airportsToRender, optionList, highlightMatch) { 	
 	var divString = '';
	if (airportsToRender.length == 0) {		
		//this.fromBoxListDiv.innerHTML="&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;There are no cities matching your request. Try again or click on the + to see valid destination cities.";
		this.setBoxOpen(false);
		//document.onclick = this.closeFromBoxListDiv.bindAsEventListener(this);
	} else {
			
		this.fromBoxListDiv.style.display='block';
		this.setBoxOpen(true);

		this.fromBoxListDiv.innerHTML = optionList;

		this.fromBoxListDiv.className = 'fromCityBoxListDiv';		
		document.getElementById('cityBoxFrame').className = 'fromCityBoxFrame';		
		if (isHomePage == null || !isHomePage) {
			this.fromBoxListDiv.style.top = getAbsTop(this.fromBox)-5 + "px";
			document.getElementById('cityBoxFrame').style.top = getAbsTop(this.fromBox)-5 + "px";
		}

		//CR#362 - Adjustment for the drop down list
		document.getElementById('cityBox').style.overflowX = "hidden";
		
		for (var x=0;x < airportsToRender.length; x++) {
			var currentAirport = airportsToRender[x];
			new ToSelection(currentAirport, this.fromBox, this.fromField, null, null, this.fromBoxListDiv, this, true);
		}

		if (airportsToRender.length > 0) {			
			document.onclick = this.closeFromBoxListDiv.bindAsEventListener(this);	
		}
	}

  },
  closeFromBoxListDiv : function (evt) {
 	if (evt.target) targ = evt.target
	else if (evt.srcElement) targ = evt.srcElement	
	if (targ.id.indexOf("fromBoxPlusSign") == -1) {
		if (this.boxOpen) {
			this.fromBoxListDiv.style.display='none';
			this.hideShowFields(false);
	 		if (this.fromField.value == '') {
	 			this.fromBox.value = '';
	 		} else {
				var previousAirport = getObjectFromArrayByCode(this.fromField.value, this.dataContainer.getAirports());
				this.fromBox.value = previousAirport.toStringNameOnly();				
			}
			this.setBoxOpen(false);
		}
	}
  },
  setBoxOpen : function (boxOpen) {
  	this.boxOpen = boxOpen;
	this.hideShowFields(boxOpen);
	this.hideShowFromBoxFrame(boxOpen);
	if (!boxOpen) {
		this.currentSelection = "";
	}	
  },
  hideShowFromBoxFrame : function (hide) {
  	if (hide) {		
		document.getElementById('cityBoxFrame').style.display ="block";
  	} else {
	  	document.getElementById('cityBoxFrame').style.display ="none";
	  	this.fieldChange = true;
	}  	
  },
  hideShowFields : function (hide) {
    for (var i=0; i < this.fieldsToHide.length; i++) {
		if (hide) {
			$(fieldsToHide[i]).style.visibility="hidden";
		} else {
			$(fieldsToHide[i]).style.visibility="visible";
		}
	}
  }
}

/*
 * this object is the control object for the To text Box.
 * It sets up initial data and handles any expected events for the box.
 * 
 * Most importantly it handles the keyup event which will populate the available
 * to airports.
 */
var ToBoxControl = Class.create();
ToBoxControl.prototype = {
  initialize : function (fieldIndex, fromFieldId, toFieldId, toBoxId, nextFieldId, nextBoxId, toBoxListDivId, toBoxPlusSign, thisForm, fieldsToHide, dataContainer, styleClass) {  
	this.fieldIndex = $(fieldIndex);
    this.fromField = $(fromFieldId);
    this.toField = $(toFieldId);
    this.toBox = $(toBoxId);
    this.nextField = $(nextFieldId);
    this.nextBox = $(nextBoxId);
    this.toBoxListDiv = $(toBoxListDivId);    
    this.toBoxPlusSign = $(toBoxPlusSign);
	this.thisForm = $(thisForm);
	this.currentSelection = "";
	this.fieldsToHide = fieldsToHide;
	//this.dataContainer = dataContainer;	
	this.dataContainer = new DataContainer(dataContainer.myJSONObject);
	this.styleClass = styleClass;
	this.toBox.onkeydown = this.toBoxKeyDown.bindAsEventListener(this);
	this.toBox.onkeyup = this.toBoxKeyUp.bindAsEventListener(this);
	this.toBox.onfocus = this.toBoxFocus.bindAsEventListener(this);
	this.toBoxPlusSign.onclick = this.toBoxPlusSignClick.bindAsEventListener(this);
	this.boxOpen = false;
	this.inputType = 'textBox';	
	this.toBoxPlusSignOptionList = null;
	this.fromValue = '';
  },
  toBoxKeyDown : function (evt) {	
	if(evt != null && (evt.keyCode==40)){  // key down
		var predictiveTable = $("predictiveLookUp");		
		if(predictiveTable != null) {
			var anchorTags = predictiveTable.getElementsByTagName("a");
			if (this.currentSelection == "") {
				var firstItem = anchorTags[0];
				this.currentSelection = firstItem;
				changeBkgrnd(firstItem);
			} else {
				for (var i=0; i < anchorTags.length; i++) {
					if (Element.hasClassName(anchorTags[i], "selected")) {
						changeBkgrnd_Blur(anchorTags[i]);
						// if not the last item
						if (i < (anchorTags.length - 1)) {
							nextItem = anchorTags[i+1];
						// ie we are on the last item, go to first
						} else {
							nextItem = anchorTags[0];
						}
						this.currentSelection = nextItem;
						changeBkgrnd(nextItem);
						i = anchorTags.length;
					}
				}
			}
		}
		fixScrollPosition(this.toBoxListDiv, this.currentSelection);
		return false;
	} else if(evt != null && evt.keyCode==38) {   // key up
		var predictiveTable = $("predictiveLookUp");
		if(predictiveTable != null) {
			var anchorTags = predictiveTable.getElementsByTagName("a");			
			if (this.currentSelection != "") {
				for (var i=0; i < anchorTags.length; i++) {
					if (Element.hasClassName(anchorTags[i], "selected")) {
						changeBkgrnd_Blur(anchorTags[i]);
						// if not the last item
						if (i > 0) {
							nextItem = anchorTags[i-1];
						// on the first item, go to the last
						} else {
							nextItem = anchorTags[anchorTags.length - 1];
						}
						this.currentSelection = nextItem;
						changeBkgrnd(nextItem);
						i = anchorTags.length;
					}
				}
			// select last item
			} else {
				var lastItem = anchorTags[anchorTags.length - 1];
				this.currentSelection = lastItem;
				changeBkgrnd(lastItem);
			}
		}
		fixScrollPosition(this.toBoxListDiv, this.currentSelection);
		return false;
	} else if(evt != null && evt.keyCode==13) {  // key enter		
		if (this.currentSelection != "") {
			this.currentSelection.onclick();
		} else {
			if (this.toBoxListDiv.getElementsByTagName("a").length==1) {
				this.toBoxListDiv.getElementsByTagName("a")[0].onclick();
			}
		}
	} else if (evt != null && evt.keyCode == 9) {
		if (this.currentSelection != "") {
			this.currentSelection.onclick();
		} else {
			this.toBoxListDiv.getElementsByTagName("a")[0].onclick();
		}
	}
  },
  toBoxKeyUp : function (evt) {   				
	if(evt == null || evt.keyCode==40 || evt.keyCode==38 || evt.keyCode==13 || evt.keyCode==9 || evt.keyCode==37 || evt.keyCode==39 ) {  
	} else {
		if (this.toBox.value == '') {			
			this.toBox.value == '';
			this.toField.value = '';			
		} else {
			this.currentSelection = "";
	  		var oThis = this;
	  		if (oThis.fromField.value == '') {
		  		// do nothing
	  		} else if (oThis.fromValue != oThis.fromField.value || oThis.dataContainer.toAirports == null) {
			  	oThis.fromValue = oThis.fromField.value;
				http_request = getXmlHttpRequestObject();
				//CR#362 - Adjustment for the drop down list
				if (ajax_url.indexOf("?") < 0)
					http_request.open("GET", ajax_url + '?origin=' + oThis.fromField.value+'&idx='+oThis.fieldIndex, true);	
				else
					http_request.open("GET", ajax_url + '&origin=' + oThis.fromField.value+'&idx='+oThis.fieldIndex, true);		
				http_request.onreadystatechange = function() {oThis.populateToMatchingAirportsRequest(evt)}; 		
				http_request.send(null);
			} else {
				oThis.populateToMatchingAirports(evt);
			}
  		}
	}
  },
  toBoxFocus : function (evt) {
  	this.toBox.select();
  	
  },
  toBoxPlusSignClick : function (evt) {  
  	if (this.boxOpen) {
		this.toBoxListDiv.style.display='none';
		this.hideShowFields(false);
		this.setBoxOpen(false);
  	} else {	  	
	  	this.toBox.focus();
	  	var oThis = this;
	  	if (oThis.fromField.value == '') {
	  		// do nothing
	  	} else if (oThis.fromValue != oThis.fromField.value || this.toBoxPlusSignOptionList == null) {
		  	oThis.fromValue = oThis.fromField.value;
		  	http_request = getXmlHttpRequestObject();
			//CR#362 - Adjustment for the drop down list
			if (ajax_url.indexOf("?") < 0)
				http_request.open("GET", ajax_url + '?origin=' + oThis.fromField.value+'&idx='+oThis.fieldIndex, true);	
			else
				http_request.open("GET", ajax_url + '&origin=' + oThis.fromField.value+'&idx='+oThis.fieldIndex, true);		
			http_request.onreadystatechange = function() {oThis.populateToAllAirports(evt)}; 		
			http_request.send(null);			
		} else {
		  	var matchingAirports = getAirportsFromAirportCodes(this.dataContainer.getToAirports(), this.dataContainer.getAirports());
			var validAirports = getValidToAirports(this.fromField.value, matchingAirports, this.dataContainer);
	
		  	this.populateToOptions(evt, validAirports, this.toBoxPlusSignOptionList, false);
		  	
		  	var predictiveTable = $("predictiveLookUp");
			var anchorTags = predictiveTable.getElementsByTagName("a");	
			for (var i=0; i < anchorTags.length; i++) {
				if (("to" + this.toField.value) == anchorTags[i].id) {
					this.currentSelection = anchorTags[i];
					changeBkgrnd(anchorTags[i]);
					fixScrollPosition(this.toBoxListDiv,this.currentSelection);
				}
			}
		}
	}
  },
  populateToAllAirports : function (evt) {
	if (http_request.readyState == 4) {
		if (http_request.status == 200) {
			this.dataContainer.toAirports = http_request.responseText.parseJSON();
		  	var matchingAirports = getAirportsFromAirportCodes(this.dataContainer.getToAirports(), this.dataContainer.getAirports());
			var validAirports = getValidToAirports(this.fromField.value, matchingAirports, this.dataContainer);
	
			this.populateToAllAirportsOptionList(evt, validAirports);			
		  	this.populateToOptions(evt, validAirports, this.toBoxPlusSignOptionList, false);
		  	
		  	var predictiveTable = $("predictiveLookUp");
			var anchorTags = predictiveTable.getElementsByTagName("a");	
			for (var i=0; i < anchorTags.length; i++) {
				if (("to" + this.toField.value) == anchorTags[i].id) {			
					this.currentSelection = anchorTags[i];
					changeBkgrnd(anchorTags[i]);
					fixScrollPosition(this.toBoxListDiv,this.currentSelection);
				}
			}
		}
	}
  }, 
  populateToAllAirportsOptionList : function (evt, validAirports) {
	var optionListStrC1="";
	var singleColumnLength=5;
	var recordCount=0;
	singleColumnLength=(singleColumnLength<validAirports.length/2)?(validAirports.length/2):singleColumnLength;
	for (var x=0;x < validAirports.length; x++) {
		var currentAirport = validAirports[x];
		optionListStrC1=optionListStrC1+getAirportAsHTMLString(currentAirport, this.toBox.value, false, false);
		recordCount++;
	}

	this.toBoxPlusSignOptionList =
		"<table id=\"predictiveLookUp\">" + "<tr>" +
		"<td valign=\"top\">" + optionListStrC1 + "</td>" +
		"</tr>" + "</table>";	
  },
  populateToMatchingAirports : function (evt) {
  	var matchingAirports = getAirportsThatMatchString(this.toBox.value, this.dataContainer.getToAirports(), this.dataContainer.getAirports());  	
	var validAirports = getValidToAirports(this.fromField.value, matchingAirports, this.dataContainer);
			
	var optionListStrC1="";
	var singleColumnLength=5;
	var recordCount=0;
	singleColumnLength=(singleColumnLength<validAirports.length/2)?(validAirports.length/2):singleColumnLength;
	for (var x=0;x < validAirports.length; x++) {
		var currentAirport = validAirports[x];
		optionListStrC1=optionListStrC1+getAirportAsHTMLString(currentAirport, this.toBox.value, true, false);
		recordCount++;
	}

	optionList =
		"<table id=\"predictiveLookUp\">" + "<tr>" +
		"<td valign=\"top\">" + optionListStrC1 + "</td>" +
		"</tr>" + "</table>";
			
	this.populateToOptions(evt, validAirports, optionList, true);
  },
  populateToMatchingAirportsRequest : function (evt) {
	if (http_request.readyState == 4) {
		if (http_request.status == 200) {
			this.dataContainer.toAirports = http_request.responseText.parseJSON();
			
			// prepare for all plus sign
			var matchingAirports = getAirportsFromAirportCodes(this.dataContainer.getToAirports(), this.dataContainer.getAirports());
			var validAirports = getValidToAirports(this.fromField.value, matchingAirports, this.dataContainer);
			this.populateToAllAirportsOptionList(evt, validAirports);
			
			this.populateToMatchingAirports(evt);			
		}
	}
  }, 
  populateToOptions : function (evt, airportsToRender, optionList, highlightMatch) {  	
 	var divString = '';
	var homePageTabs=$("homePageTabs");  	
	if (airportsToRender.length == 0) {
		this.setBoxOpen(false);		
	} else {
		this.toBoxListDiv.style.display='block';
		this.setBoxOpen(true);
		
		var toSelections = new Array();
		
		this.toBoxListDiv.innerHTML = optionList;
		
		this.toBoxListDiv.className = this.styleClass + "CityBoxListDiv";
		document.getElementById('cityBoxFrame').className = this.styleClass + "CityBoxFrame";
		
		if (isHomePage == null || !isHomePage) {
		 this.toBoxListDiv.style.top = getAbsTop(this.toBox)-5 + "px";
		 document.getElementById('cityBoxFrame').style.top = getAbsTop(this.toBox)-5 + "px";
		}		
		
		for (var x=0;x < airportsToRender.length; x++) {
			var currentAirport = airportsToRender[x];
			new ToSelection(currentAirport, this.toBox, this.toField, this.nextBox, this.nextField, this.toBoxListDiv, this, false);
		}

		if (airportsToRender.length > 0) {
			document.onclick = this.closeToBoxListDiv.bindAsEventListener(this);
		}
	}

  },
  closeToBoxListDiv : function (evt) {
 	if (evt.target) targ = evt.target
	else if (evt.srcElement) targ = evt.srcElement
	if (targ.id.indexOf("toBoxPlusSign") == -1) {
		if (this.boxOpen) {
			this.toBoxListDiv.style.display='none';
			this.hideShowFields(false);
	 		if (this.toField.value == '') {
	 			this.toBox.value = '';
	 		} else {
				var previousAirport = getObjectFromArrayByCode(this.toField.value, this.dataContainer.getAirports());
				this.toBox.value = previousAirport.toStringNameOnly();
			}
			this.setBoxOpen(false);
		}
	}
  },
  setBoxOpen : function (boxOpen) {
  	this.boxOpen = boxOpen;
	this.hideShowFields(boxOpen);
	this.hideShowToBoxFrame(boxOpen);
	if (!boxOpen) {
		this.currentSelection = "";
	}
  },
  hideShowToBoxFrame : function (hide) {
  	if (hide) {
		document.getElementById('cityBoxFrame').style.display ="block";
  	} else {
	  	document.getElementById('cityBoxFrame').style.display ="none";
	}  	
  },
  hideShowFields : function (hide) {
    for (var i=0; i < this.fieldsToHide.length; i++) {
		if (hide) {
			$(fieldsToHide[i]).style.visibility="hidden";
		} else {
			$(fieldsToHide[i]).style.visibility="visible";
		}
	}
  },
  hideShowCloseButton : function (hide) {
    for (var i=0; i < this.hideOnlyCloseButton.length; i++) {
		if (hide) {
			$(hideOnlyCloseButton[i]).style.display="block";
		} else {
			$(hideOnlyCloseButton[i]).style.display="none";
		}
	}
  }
}

function fixScrollPosition(currentDiv, currentItem) {
	if(currentItem.offsetTop > (currentDiv.offsetHeight -20)){
		currentDiv.scrollTop = currentItem.offsetTop;
	
	}
	if(currentItem.offsetTop<currentDiv.scrollTop)
	{
		currentDiv.scrollTop = 0; 
	}
}

/**
 * this is the control object for each anchor link in the 'to' selection list.
 */
var ToSelection = Class.create();
ToSelection.prototype = {
  initialize : function (airport, toBox, toSelectionField, nextBox, nextSelectionField, toBoxListDiv, toBoxControl, updateLabel) {    
    this.airport = airport;
    this.toBox = toBox;
    this.toSelectionField = toSelectionField;
    this.nextBox = nextBox;
    this.nextSelectionField = nextSelectionField;
    this.toBoxListDiv = toBoxListDiv;
    this.toBoxControl = toBoxControl;
    this.airportHref = $("to" + airport.code);
    this.updateLabel = updateLabel;
	this.airportHref.onclick = this.airportHrefClick.bindAsEventListener(this);
  },
  airportHrefClick : function (evt) {
	this.toBoxControl.setBoxOpen(false);
	this.toBox.className = 'txt';
  	this.toSelectionField.value = this.airport.code;
  	if (this.updateLabel) {
		updateFlexibleOption(this.airport.country.code);	
		if (this.toBoxControl && this.toBoxControl.fieldIndex == 0) {
			hideShowInfantOption(this.airport.code);
		}
	}
  	this.toBox.value = this.airport.toStringNameOnly();
  	if (this.nextBox != null)
  		this.nextBox.value = this.airport.toStringNameOnly();
  	if (this.nextSelectionField != null)
  		this.nextSelectionField.value = this.airport.code;
  	//this.toSelectionField.onchange();
  	this.toBoxListDiv.innerHTML = '';
	this.toBoxListDiv.style.display='none';
  }
}

/**
 * gets the matching airports and validates that the airport is valid for the 
 * from/to combination it will form.
 */
function getValidToAirportsThatMatchString(fromAirport, stringToMatch, dataContainer) {	
	var airportCodeList = dataContainer.getToAirports();
	var airports = dataContainer.getAirports();
	var matchingAirports = getAirportsThatMatchString(stringToMatch, airportCodeList, airports);
	// ensure all matching airports are valid for this from/to combination
	var validAirports = getValidToAirports(fromAirport, matchingAirports, dataContainer)
	return validAirports;
	
}

/**
 * takes a list of airports and returms only those that are valid for the from/to combination
 */
function getValidToAirports(fromAirport, airports, dataContainer) {

	// ensure all matching airports are valid for this from/to combination
	var validAirports = new Array();
    for (var i=0; i<airports.length;i++) {
    	var currentAirport = airports[i];
		// check if airport pair valid
			var flightItem = FlightDataCache.getFlightDataItem(dataContainer, fromAirport, currentAirport.code);
			if (flightItem.isValidFlight() || fromAirport.length == "0") {
				validAirports.push(currentAirport);					
			}
    }
	return validAirports;
}

/**
 * takes a list of airport codes and gets the airport objects for them out of the provided airport list
 *
 */
function getAirportsFromAirportCodes(airportCodes, allAirports) {
	var airports = new Array();
	for (var i=0; i<airportCodes.length;i++) {
		var currentAirport = getObjectFromArrayByCode(airportCodes[i], allAirports);
		airports.push(currentAirport);
	}
	return airports;
}

/**
 * search the airport list to find airports that match the provided string either by
 * full name or airport code.
*/
function getAirportsThatMatchString(stringToMatch, airportCodeList, airports) {
	
	var matchingAirports = new Array();
	var pattern = null;
	
	if (stringToMatch != '' && stringToMatch != null) {

		//var pattern = new RegExp("^"+stringToMatch, "i");
		//CR463 - Adding airport name to the Booking O/D List
		var pattern = new RegExp("^"+stringToMatch+"|, "+stringToMatch+"|/"+stringToMatch, "i");
	
		for (var i=0; i<airportCodeList.length;i++) {
			var currentAirport = getObjectFromArrayByCode(airportCodeList[i], airports);
			// check if code matches
			if (pattern.test(currentAirport.port.portName)) {
				matchingAirports.push(currentAirport);
			} else if (pattern.test(currentAirport.airportName)) {
				matchingAirports.push(currentAirport);
			} else if (pattern.test(currentAirport.country.countryName)) {
				matchingAirports.push(currentAirport);
			} else if (pattern.test(currentAirport.code)) {
				matchingAirports.push(currentAirport);
				
			// added by cpphowc for pax.0455
			// when encounter TYO, also match HND & NRT
			} else if (airportsOfPortCode[currentAirport.code] != null) {
				if (matchAirports(pattern, airportsOfPortCode[currentAirport.code])) {
					matchingAirports.push(currentAirport);
				}
			}
			// added by cpphowc for pax.0455
		}
	} else {
		for (var i=0; i<airportCodeList.length;i++) {
			var currentAirport = getObjectFromArrayByCode(airportCodeList[i], airports);
			matchingAirports.push(currentAirport);
		}
	}
		
	return matchingAirports;
	
}

// added by cpphowc for pax.0455
function matchAirports(pattern, airportCodes) {
	for(var j=0;j<airportCodes.length;j++){
		if (pattern.test(airportCodes[j])) {
			return true;
		}
	}
	return false;
}
// added by cpphowc for pax.0455

/**
 * returns the index of the airport code within an array
 */
function indexOfAirportByCode(code,airportArray) {
    for (var i=0;i<airportArray.length;i++) {
       if (code == airportArray[i]) {
           return i;
       }
    }

    return -1;
}

/**
 * returns the full object from an array when searching by code.
 * Assumes that the object will have a 'code' property.
 */
function getObjectFromArrayByCode(code, ourArray) {
	for (var i=0;i<ourArray.length;i++) {
	   if (code == ourArray[i].code) {
		   return ourArray[i];
	   }
	}

    return null;
}

//Gets the browser specific XmlHttpRequest Object
function getXmlHttpRequestObject() {	
	if (window.XMLHttpRequest) {		
		return new XMLHttpRequest();	
	} else if(window.ActiveXObject) {		
		return new ActiveXObject("Microsoft.XMLHTTP");	
	}
}

function updateFlexibleOption(country) {	
	var start = 0;
	if (document.getElementById('flexibleDateDiv1') != null || document.getElementById('flexibleDateDiv2') != null) {
		/*if (flexibleCountry.indexOf(country) == -1) {
			document.getElementById('flexibleDateDiv1').style.display="none";
			document.getElementById('flexibleDateDiv2').style.display="block";

			for(var i = 0; i<document.getElementsByName('flexibleDate').length; i++){
				if (document.getElementsByName('flexibleDate')[i].type && document.getElementsByName('flexibleDate')[i].type == "radio"){
					start++;
					if (start==3)
						document.getElementsByName('flexibleDate')[i].checked = true;
					else
						document.getElementsByName('flexibleDate')[i].checked = false;
				}
			}
		} else {*/
			document.getElementById('flexibleDateDiv1').style.display="block";
			document.getElementById('flexibleDateDiv2').style.display="none";

			for(var i = 0; i<document.getElementsByName('flexibleDate').length; i++){
				if (document.getElementsByName('flexibleDate')[i].type && document.getElementsByName('flexibleDate')[i].type == "radio"){
					start++;
					if (start==2)
						document.getElementsByName('flexibleDate')[i].checked = true;
					else
						document.getElementsByName('flexibleDate')[i].checked = false;
				}
			}
		//}
	}
}

function hideShowInfantOption(portCode) {
	if (document.getElementById('paxInfantDiv1') != null && document.getElementById('paxInfantDiv2') != null) {
		if (nonInfantPort.indexOf(portCode) == -1) {
			document.getElementById('paxInfantDiv1').style.display ="block";
			document.getElementById('paxInfantDiv2').style.display ="none";
  		} else {
			document.getElementById('paxInfantDiv1').style.display ="none";
			document.getElementById('paxInfantDiv2').style.display ="block";
			
			document.getElementById('infant').selectedIndex = 0;
		}
	} 
}
