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.toAirports = dataContainer.getToAirports();
  	this.classes = dataContainer.getClasses();
  	this.matrix = dataContainer.getMatrix();
    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;
  },
  // could move this data into matrix and thereby moving business logic out of front end
  isDomestic : function () {
	if (this.fromAirport.country == this.toAirport.country) {
		return true;
	}
	return false;
  },
  // could move this data into matrix and thereby moving business logic out of front end
  isInternational : function () {
	if (this.fromAirport.country != this.toAirport.country
		&& !this.isTransTasman()) {
		return true;
	}
	return false;
  },
  // could move this data into matrix and thereby moving business logic out of front end
  isTransTasman : function () {
	if ((this.fromAirport.country.code == 'AU' 
		 && this.toAirport.country.code == 'NZ')
		 ||
		(this.fromAirport.country.code == 'NZ' 
		 && this.toAirport.country.code == 'AU')) {
		return true;
	} else {
		return false;
	}
  },
  getClasses : function (departCalendar) {
  	if (this.matrixItem != null) {
  		return getClassesForFlight(this.matrixItem, this.dataContainer, departCalendar, this.fromAirport, this.toAirport);
  	}
  	
  	return new Array();
  	
  }
}

/* 
 * this object holds the basic airport data for a airport
 */
var Airport = Class.create();
Airport.prototype = {
  initialize : function (code, airportName, countryCode, countries) {
    this.code = code;
    this.airportName = airportName;
	this.country = getObjectFromArrayByCode(countryCode, countries);
  },
  getCountry : function () {
  	return this.country;
  },
  toStringNameOnly : function () {
  	return this.airportName;
  },
  toString : function () {
  	return this.toStringNoCode() + " (" + this.code + ")";
  },
  toStringAirportCodeOnly : function () {
	  return this.toStringNoCode() + "<span class=\'aCode\'>" + " (" + this.code + ")" + "</span>";
  },
  toStringNoCode : function () {
  	return this.airportName + ", " + this.country.countryName;
  },
  // this assumes toString format of Airport, Country (AirportCode)
  toStringWithHighlightedAirport : function (highlightValue) {
  	var airportText = this.toString();
	var indexOfMatch = airportText.toLowerCase().indexOf(highlightValue.toLowerCase());
	var countryMatchflag = "flagno";


	// check if index match is in airport name, if not then look for match in code
	if (indexOfMatch > this.airportName.length) {
		var lengthOfStringNoCode = this.toStringNoCode().length;
		var indexAfterCountry = airportText.substring(lengthOfStringNoCode).toLowerCase().indexOf(highlightValue.toLowerCase());
		indexOfMatch = lengthOfStringNoCode + indexAfterCountry;
		countryMatchflag = "flagyes";
	}
	if(countryMatchflag == "flagno"){
		var beforeHighlight = airportText.substring(0, indexOfMatch);
		var highlighted		= airportText.substring(indexOfMatch, indexOfMatch + highlightValue.length);
		var afterHighlight	= airportText.substring(indexOfMatch + highlightValue.length,airportText.length);
		var airportCodeAlone = afterHighlight.substring(afterHighlight.lastIndexOf("("),afterHighlight.lastIndexOf(")")+1);
		var afterHightlightCode  = afterHighlight.substring(0,afterHighlight.lastIndexOf("("));
		return beforeHighlight + "<strong>" + highlighted + "</strong>" +  afterHightlightCode + "<span class=\'aCode\'>" + airportCodeAlone + "</span>";
	} else {
		var beforeCodeHighlight	 = airportText.substring(0, indexOfMatch); // Takes the code upto where it matches (Rome , Italy ( --> when you type 'f')
		var lastHighlightedValue = beforeCodeHighlight.substring(airportText.lastIndexOf("("));// It gives the last index value where it matches "("
		var beforeHighlightSpan  = airportText.substring(0, (indexOfMatch-highlightValue.length)); // it will give now as (Rome , Italy ")
		var codeHighlighted      = airportText.substring(0, ((indexOfMatch+1) - (highlightValue.length)));
		var highlighted1		 = airportText.substring(indexOfMatch, indexOfMatch + highlightValue.length);
		var afterHighlight1		 = airportText.substring(indexOfMatch + highlightValue.length,airportText.length)
		if( highlightValue.length == 2){
			return beforeHighlightSpan + "<span class=\'aCode\'>" + lastHighlightedValue + "<strong>" + highlighted1 + "</strong>" +  afterHighlight1 +"</span>";
		} else if(highlightValue.length == 1){
			return beforeHighlightSpan + "<span class=\'aCode\'>"+ "(" + "<strong>" + highlighted1 + "</strong>" +  afterHighlight1 +"</span>";				
		} else {
			return codeHighlighted + "<span class=\'aCode\'>"+"(" + "<strong>" + highlighted1 + "</strong>" +  afterHighlight1 +"</span>";
		}
	}

  }
}

/**
 * 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) {
	
//	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\" ";
		}
	}
	/*anchor + */
	var openingAnchorTag = "<a onFocus='changeBkgrnd(this)' onBlur='changeBkgrnd_Blur(this)' href='javascript:void(0)' id='to" + currentAirport.code + "'" + highlight + "/>";
	var airportText;
	if (highlightMatch) {
		airportText = currentAirport.toStringWithHighlightedAirport(highlightValue);
	} else {
		airportText = currentAirport.toStringAirportCodeOnly();
	}
	var closingAnchorTag = "</a>";
	return openingAnchorTag + airportText + closingAnchorTag;
}


/* 
 * this object holds the basic data for a booking class
 */
var BookingClass = Class.create();
BookingClass.prototype = {
  initialize : function (code, value, className) {
    this.code = code;
    this.value = value;
    this.className = className;
  }
}
  
/* 
 * 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 From Selection Box.
 * It sets up initial data and handles any expected events for the box.
 */
var FromBoxControl = Class.create();
FromBoxControl.prototype = {
  initialize : function (fromBoxId, dataContainer, defaultValue, showCountries, fromHeader) {
    this.fromBox = $(fromBoxId);
	this.popularFromAirports = dataContainer.getPopularFromAirports();
	this.fromAirports = dataContainer.getFromAirports();
	this.airports = dataContainer.getAirports();
	this.defaultValue = defaultValue;
	this.showCountries = showCountries;
	this.fromHeader = fromHeader;
	this.fromBox.onchange = this.fromBoxChange.bindAsEventListener(this);
	this.populateFromBox();
  },
  fromBoxChange : function (evt) {
  	
  	
  },
  populateFromBox : function () {
    var selected=false;
	var selectedIndex=0;
	this.fromBox.options.length=0;
	// place select from city at top
	var index = 0;
	this.fromBox.options[index]=new Option(this.fromHeader,'');
	index++;
	// put in seperator
	this.fromBox.options[index]=new Option('-----------------','separator');
	index++;
	// now put popular airports
	if (this.popularFromAirports != null) {
		
	
		var popArray = new Array();
		for (var i=0;i<this.popularFromAirports.length;++i){
			var currentAirport = getObjectFromArrayByCode(this.popularFromAirports[i], this.airports);
			popArray[i] = currentAirport;
		}
		//sorting removed since its handled at java end
		//popArray.sort(function(a,b) { return a.airportName-b.airportName; });
		for (var i=0;i<popArray.length;++i, index++){
		
			var currentAirport = popArray[i];
			this.fromBox.options[index]=new Option(currentAirport.airportName,currentAirport.code);
			if (!selected && this.defaultValue == currentAirport.code) {
				selectedIndex = index;
				selected = true;
			}
		}
		// put in seperator
		this.fromBox.options[index]=new Option('-----------------','separator');
		index++;
	}
	var lastDropDownCountry = "";
	// now put all airports
	var sortedArray = new Array();
 	for (var i=0;i<this.fromAirports.length;++i){
 		var currentAirport = getObjectFromArrayByCode(this.fromAirports[i], this.airports);
		sortedArray[i] = currentAirport;
 	}
	//sorting removed since its handled at java end
	//if (!this.showCountries) {
		//sortedArray.sort(compareAirportsByName);
	//}
 	for (var i=0;i<sortedArray.length;++i, index++){
 		var currentAirport = sortedArray[i];
 		if (this.showCountries && currentAirport.country.countryName != lastDropDownCountry) {
			this.fromBox.options[index]=new Option(currentAirport.country.countryName,"");
			this.fromBox.options[index].className = "cityDropDownCountry";
			index++;
			lastDropDownCountry = currentAirport.country.countryName;
 		}
		this.fromBox.options[index]=new Option(currentAirport.airportName,currentAirport.code);
		if (!selected && this.defaultValue == currentAirport.code) {
			selectedIndex = index;
			selected = true;
		}
 	}
	this.fromBox.selectedIndex = selectedIndex;
  }
}

	function compareAirportsByName(a,b) {
		if (a.airportName < b.airportName) {
			return -1;
		} else if (a.airportName > b.airportName) {
		 	return 1;
		} else {
		 	return 0;
		}
	}

/*
 * this object is the control object for the To Selection Box.
 * It sets up initial data and handles any expected events for the box.
 */
var ToDropControl = Class.create();
ToDropControl.prototype = {
  initialize : function (fromBoxId, toBoxId, dataContainer, departCalendar, showCountries, toHeader) {
    this.fromBox = $(fromBoxId);
    this.toBox = $(toBoxId);
    this.departCalendar = departCalendar;
    this.dataContainer = dataContainer;
	this.showCountries = showCountries;
	this.toHeader = toHeader;
	this.toAirports = this.dataContainer.getToAirports();
	this.popularToAirports = this.dataContainer.popularToAirports;
	this.airports = this.dataContainer.getAirports();
	this.toBox.onchange = this.toBoxChange.bindAsEventListener(this);
	this.inputType = 'selectBox';
	this.populateToBox();

  },
  toBoxChange : function (evt) {
  	
  	
  },
  populateToBox : function (initialValue) {
	this.toBox.options.length=0;
	// place select from city at top
	var index = 0;
	var selectedIndex = 0;
	this.toBox.options[index]=new Option(this.toHeader,'');
	index++;
	// put in seperator
	this.toBox.options[index]=new Option('-----------------','separator');
	index++;
	
	// now put popular airports
	if (this.popularToAirports != null) {
		for (var i=0;i<this.popularToAirports.length;++i, index++){
			var currentAirport = getObjectFromArrayByCode(this.popularToAirports[i], this.airports);
			this.toBox.options[index]=new Option(currentAirport.airportName,currentAirport.code);
			if (this.defaultValue == currentAirport.code) {
				selectedIndex = index;
			}
		}
		// put in seperator
		this.toBox.options[index]=new Option('-----------------','separator');
		index++;
	}

	var lastDropDownCountry = "";
	// now put all airports
 	for (var i=0;i<this.toAirports.length;i++){
 		var currentAirport = getObjectFromArrayByCode(this.toAirports[i], this.airports);
 		if (this.showCountries && currentAirport.country.countryName != lastDropDownCountry) {
			this.toBox.options[index]=new Option(currentAirport.country.countryName,"");
			this.toBox.options[index].className = "cityDropDownCountry";
			index++;
			lastDropDownCountry = currentAirport.country.countryName;
 		}
 		if (this.fromBox.value != '') {
			var flightDataItem = FlightDataCache.getFlightDataItem(this.dataContainer, this.fromBox.value, currentAirport.code);
			// check that flight combo is valid, if yes add to select
			if (flightDataItem.isValidFlight()) {
				this.toBox.options[index]=new Option(currentAirport.airportName,currentAirport.code);
				if (currentAirport.code == initialValue) {
					selectedIndex = index;
				}
				index++;
			}
 		} else {
			this.toBox.options[index]=new Option(currentAirport.airportName,currentAirport.code);
			if (currentAirport.code == initialValue) {
				selectedIndex = index;
			}
			index++;
 		}
 	}
 	
 	this.toBox.selectedIndex = selectedIndex;
 	
  }
}

/*
 * 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 (fromBoxId, toBoxId, toBoxListDivId, toBoxPlusSign, toSelectionFieldId, thisForm, fieldsToHide, dataContainer,toBoxCloseButtonId,isHomePage) {
    this.fromBox = $(fromBoxId);
    this.toBox = $(toBoxId);
    this.toBoxListDiv = $(toBoxListDivId);
    this.toSelectionField = $(toSelectionFieldId);
    this.toBoxPlusSign = $(toBoxPlusSign);
	this.thisForm = $(thisForm);
	this.currentSelection = "";
	this.fieldsToHide = fieldsToHide;
	this.dataContainer = dataContainer;
	this.isHomePage = isHomePage;
	this.toBoxCloseButton = $(toBoxCloseButtonId);
	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.popularFromAirports = dataContainer.getPopularFromAirports();
	this.boxOpen = false;
	this.inputType = 'textBox';
  },
  toBoxKeyDown : function (evt) {
	if(evt != null && (evt.keyCode==40)){  	
		var predictiveTable = $(this.toSelectionField.id+"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) {  
		var predictiveTable = $(this.toSelectionField.id+"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) {
		if (this.currentSelection != "") {
			this.currentSelection.onclick();
		} else {
			if (this.toBoxListDiv.getElementsByTagName("a").length==1) {
				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 {
		this.currentSelection = "";
		this.populateToMatchingAirports(evt);
	}
  },
  toBoxFocus : function (evt) {
  	this.toBox.select();
  	
  },
  toBoxPlusSignClick : function (evt) {
  	this.populateToAllAirports(evt);
  	this.toBox.focus();
	var predictiveTable = $(this.toSelectionField.id+"predictiveLookUp");
	var anchorTags = predictiveTable.getElementsByTagName("a");
	for (var i=0; i < anchorTags.length; i++) {
		if (("to" + this.toSelectionField.value) == anchorTags[i].id) {
			this.currentSelection = anchorTags[i];
			changeBkgrnd(anchorTags[i]);
			fixScrollPosition(this.toBoxListDiv,this.currentSelection);
		}
	}
  },
  populateToAllAirports : function (evt) {
	var toAirports = getAirportsFromAirportCodes(this.dataContainer.getToAirports(), this.dataContainer.getAirports());
	var validAirports = getValidToAirports(this.fromBox.value, toAirports, this.dataContainer);
  	this.populateToOptions(evt, validAirports, false);
  	
  },
  populateToMatchingAirports : function (evt) {
	var matchingAirports = getValidToAirportsThatMatchString(this.fromBox.value, this.toBox.value, this.dataContainer);
	this.populateToOptions(evt, matchingAirports, true);
  },
  populateToOptions : function (evt, airportsToRender, highlightMatch) {
 	var divString = '';
	this.setBoxOpen(true);
	if (airportsToRender.length == 0) {
		
		$j('.predictiveTextBox').parent().hide();
		$j(this.toBoxListDiv).attr('class','predictiveTextBox toCityBoxNoMatches');
		$j(this.toBoxListDiv).parent().show();
		
		this.toBoxListDiv.innerHTML=this.dataContainer.noMatchingCitiesText;
		this.toBoxCloseButton.onclick = this.closeToBoxListDiv.bindAsEventListener(this);
	} else {
		var toSelections = new Array();
		var optionListStrC1="";
		var optionListStrC2="";
		var singleColumnLength=5;
		var recordCount=0;
		singleColumnLength=(singleColumnLength<airportsToRender.length/2)?(airportsToRender.length/2):singleColumnLength;
		for (var x=0;x < airportsToRender.length; x++) {
			var currentAirport = airportsToRender[x];
			if (recordCount < singleColumnLength) {
				optionListStrC1=optionListStrC1+"<li>"+getAirportAsHTMLString(currentAirport, this.toBox.value, highlightMatch) + "</li>";
			} else {
				optionListStrC2=optionListStrC2+"<li>"+getAirportAsHTMLString(currentAirport, this.toBox.value, highlightMatch) + "</li>";
			}
			recordCount++;
		}
		optionList="<div id=\""+this.toSelectionField.id+"predictiveLookUp\" class=\"clearit\"><ul class=\"left\">"+optionListStrC1+"</ul>";
		
		if (optionListStrC2 != "")
		{
			optionList=optionList+"<ul class=\"left\">"+optionListStrC2+"</ul>";
		}

		optionList=optionList + "</div>";

		if(recordCount < "6")
		{
			$j('.predictiveTextBox').parent().hide();
			$j(this.toBoxListDiv).attr('class','predictiveTextBox toCityBoxSingleColumn');
			$j(this.toBoxListDiv).parent().show();
		}
		else if(recordCount > "5")
		{
			$j('.predictiveTextBox').parent().hide();
			$j(this.toBoxListDiv).attr('class','predictiveTextBox toCityBoxDoubleColumns');
			$j(this.toBoxListDiv).parent().show();
		}
		else
		{
		}

		this.toBoxListDiv.innerHTML = optionList;
		this.toBoxCloseButton.onclick = this.closeToBoxListDiv.bindAsEventListener(this);
				
		for (var x=0;x < airportsToRender.length; x++) {
			var currentAirport = airportsToRender[x];
			new ToSelection(currentAirport, this.toBox, this.toSelectionField, this.toBoxListDiv, this);
		}
		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 != this.toBoxPlusSign.id){
			if (this.boxOpen)
			{
				
				$j('.predictiveTextBox').parent().hide();
				
				this.hideShowFields(false);
				if (this.toSelectionField.value == '')
				{
					this.toBox.value = '';
				}
				else
				{
					var previousAirport = getObjectFromArrayByCode(this.toSelectionField.value, this.dataContainer.getAirports());
					this.toBox.value = previousAirport.toStringNameOnly();
				}
				this.setBoxOpen(false);
			}
	}
  },
  setBoxOpen : function (boxOpen) {
  	this.boxOpen = boxOpen;
	this.hideShowFields(boxOpen);
	this.hideShowCloseButton(boxOpen);
	if (!boxOpen) {
		this.currentSelection = "";
	}
  },
  hideShowFields : function (hide) {
    for (var i=0; i < this.fieldsToHide.length; i++) {
		if (hide) {
			if($j.browser.version.substr(0,3) == '6.0' && $j.browser.msie) $j('#'+this.fieldsToHide[i]).css('visibility','hidden');
		} else {
			if($j.browser.version.substr(0,3) == '6.0' && $j.browser.msie) $j('#'+this.fieldsToHide[i]).css('visibility','visible');
		}
	}
  },
  hideShowCloseButton : function (hide) {
	if (hide) {
		$j(this.toBoxCloseButton).parent().show();
	} else {
		$j(this.toBoxCloseButton).parent().hide();
	}
  }
}

function fixScrollPosition(currentDiv, currentItem) {
	if(currentItem.offsetTop > (currentDiv.offsetHeight -20)){
		currentDiv.scrollTop = currentItem.offsetTop;
	
	}
	if(currentItem.offsetTop<currentDiv.scrollTop)
	{
		currentDiv.scrollTop = 0; 
	}
}
/*    

 * this object is the control object for when a 'from' or 'to' is selected and we are
 * required to do something.
 */
var FromToHandler = Class.create();
FromToHandler.prototype = {
  initialize : function (fromBoxControl, toBoxControl, classBoxId, intDomConvertFunction, dataContainer, departCalendar) {
	this.fromBoxControl = fromBoxControl;
	this.toBoxControl = toBoxControl;
	if (this.toBoxControl.inputType == 'textBox') {
		this.toSelectionField = this.toBoxControl.toSelectionField;
	} else {
		this.toSelectionField = this.toBoxControl.toBox;
	}
    this.toBox = this.toBoxControl.toBox;
	this.classBox = $(classBoxId);
	this.departCalendar = departCalendar;
	this.intDomConvertFunction = intDomConvertFunction;
	this.fromBoxControl.fromBox.onchange = this.fromToChange.bindAsEventListener(this);
	this.toSelectionField.onchange = this.fromToChange.bindAsEventListener(this);
	this.dataContainer = dataContainer;
  },
  fromToChange: function (evt) {
	// now if the box is open, reload the contents
	if (this.toBoxControl.inputType == 'textBox' && this.toBoxControl.boxOpen) {
		this.toBoxControl.populateToMatchingAirports(evt);
	} else {
		if (this.toBoxControl.inputType == 'selectBox') {
			this.toBoxControl.populateToBox(this.toSelectionField.value);
		}
		if (this.fromBoxControl.fromBox.value != '' && this.toSelectionField.value != '') {
			var flightDataItem = FlightDataCache.getFlightDataItem(this.dataContainer, this.fromBoxControl.fromBox.value, this.toSelectionField.value);
			// check that flight combo is still valid, if not clear the to box
			if (!flightDataItem.isValidFlight()) {
				if (this.toBoxControl.inputType == 'textBox') {
					this.toSelectionField.value = '';
					this.toBox.value = '';
				} else {
					this.toSelectionField.selectedIndex = 0;
				}
				this.intDomConvertFunction();
			} else {
				if (flightDataItem.isInternational()) {
					this.populateClasses(flightDataItem);
				}
				this.intDomConvertFunction(flightDataItem);
			}
		} else { // To get rid of 'Premium Economy' from the drop down, if its already present
			this.populateClassesForRoute();
			// call this method to setup default look (ie when we dont have the citypair)
			this.intDomConvertFunction();
		}
	}
  },
  populateClasses : function (flightDataItem) {
	if (this.classBox != null) {
	  	if (flightDataItem != null){
			var classes = flightDataItem.getClasses(this.departCalendar);
		}else{
			var classes = getClassesForFlight(null, this.dataContainer, this.departCalendar, this.fromAirport, this.toAirport);
		}
		var indexSelected = this.classBox.selectedIndex;
		this.classBox.options.length=0;
		for (var i=0;i<classes.length;i++){
			var currentClass = classes[i];
			this.classBox.options[i]=new Option(currentClass.className,currentClass.value);
		}
		if(indexSelected != -1){
			this.classBox.selectedIndex = indexSelected;
		}
  	}
  },
  populateClassesForRoute : function () {
	if (this.fromBoxControl.fromBox.value != "" && this.toSelectionField.value != ""){
		var flightDataItem = FlightDataCache.getFlightDataItem(this.dataContainer, this.fromBoxControl.fromBox.value, this.toSelectionField.value, this.toBoxControl.departCalendar);
		this.populateClasses(flightDataItem)
	}else{
		this.populateClasses();
	}
  },
  setInitialValues : function (from, to) {
	// setup frombox
	var valueMatched = false;
	for(var i=0;i<this.fromBoxControl.fromBox.options.length;++i){
		if(this.fromBoxControl.fromBox.options[i].value==from){
			this.fromBoxControl.fromBox.selectedIndex=i;
			valueMatched = true;
			break;
		}
	}
	if(valueMatched == false && from==''){
		// presumes element 0 is always the default eg "Select a City..."
		this.fromBoxControl.fromBox.selectedIndex=0;
	}

	if (this.toBoxControl.inputType == 'textBox' && to != null && to != '') {
		var toAirport = getObjectFromArrayByCode(to, this.dataContainer.getAirports());
		if (toAirport != null) {
			this.toBox.value = toAirport.airportName;
			this.toSelectionField.value = toAirport.code;
		}
	}
	
	// run the onchange method to ensure all is setup ok
	this.fromToChange();

	// setup tobox
	if (this.toBoxControl.inputType == 'textBox') {
//		var toAirport = getObjectFromArrayByCode(to, this.dataContainer.getAirports());
//		this.toBox.value = toAirport.airportName;
//		this.toSelectionField.value = toAirport.code;
	} else {
		var valueMatched = false;
		for(var i=0;i<this.toBoxControl.toBox.options.length;++i){
			if(this.toBoxControl.toBox.options[i].value==to){
				this.toBoxControl.toBox.selectedIndex=i;
				valueMatched = true;
				break;
			}
		}
		if(valueMatched == false && from==''){
			// presumes element 0 is always the default eg "Select a City..."
			this.toBoxControl.toBox.selectedIndex=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, toBoxListDiv, toBoxControl) {
    this.airport = airport;
    this.toBox = toBox;
    this.toSelectionField = toSelectionField;
    this.toBoxListDiv = toBoxListDiv;
    this.toBoxControl = toBoxControl;
    this.airportHref = $("to" + airport.code);
	this.airportHref.onclick = this.airportHrefClick.bindAsEventListener(this);
  },
  airportHrefClick : function (evt) {
	this.toBoxControl.setBoxOpen(false);
  	this.toSelectionField.value = this.airport.code;
  	this.toBox.value = this.airport.toStringNameOnly();
  	
  	this.toBoxListDiv.innerHTML = '';
	
	$j('.predictiveTextBox').parent().hide();
	
	if ($j('div').find('.majorCitySelected').length > 0)
	{
		var majorCitySelected = $j('div').find('.majorCitySelected').attr('class').indexOf('majorCitySelected')
		if (majorCitySelected > 0) 
		{
			var data = this.toBoxControl.popularFromAirports;
			arrivalCheckforMajorCities(data);
		}
		else
		{
			this.toSelectionField.onchange();
		}
	}
	else
	{
		this.toSelectionField.onchange();
	}
  }
}

/**
 * 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();

	if (stringToMatch != '' && stringToMatch != null) {

		if(stringToMatch.length == 1){
			var pattern = new RegExp("^" +stringToMatch , "i");
		} else {
				pattern = new RegExp("" +stringToMatch, "i");
		}

		for (var i=0; i<airportCodeList.length;i++) {
			var currentAirport = getObjectFromArrayByCode(airportCodeList[i], airports);
			// check if code matches
			if (pattern.test(currentAirport.code)) {
				matchingAirports.push(currentAirport);
			} else if (pattern.test(currentAirport.airportName)) {
				matchingAirports.push(currentAirport);
			}
		}
	}
		
	return matchingAirports;
	
}

/**
 * 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;
}

function getMatrixItem(fromIndex, toIndex, matrix, numberOfFroms, numberOfTos) {
	var itemIndex = (fromIndex * numberOfTos) + toIndex;
	var item32 = matrix.charAt(itemIndex);
	var matrixItemDecimal = parseInt(item32, 32);
	var matrixItemBoolean = matrixItemDecimal.toString(2);
	
	return matrixItemBoolean.padLeft(5,'0');
}

/*
 * checks if a matrix item is representing true or false
 */
function determineBooleanValueFromMatrixItem(matrixItem, index) {
	if (matrixItem.charAt(index) == '1') {
		return true;
	} 
	return false;	
}

/*
 * checks the matrix item to see what classes are valid for a particular from/to
 * combination
 */
function getClassesForFlight(matrixItem, dataContainer, departCalendar, fromAirport, toAirport) {
	
	var classesForFlight = new Array();

	var travelClassObjectY = getObjectFromArrayByCode("Y", dataContainer.getClasses());
	var travelClassObjectP = getObjectFromArrayByCode("P", dataContainer.getClasses());
	var travelClassObjectJ = getObjectFromArrayByCode("J", dataContainer.getClasses());
	var travelClassObjectF = getObjectFromArrayByCode("F", dataContainer.getClasses());

	if (matrixItem == null){
		if (travelClassObjectY != null){
			classesForFlight.push(travelClassObjectY);
		}
		if (travelClassObjectJ != null){
			classesForFlight.push(travelClassObjectJ);
		}
		if (travelClassObjectF != null){
			classesForFlight.push(travelClassObjectF);
		}
	}else{
		if (determineBooleanValueFromMatrixItem(matrixItem, dataContainer.getEconomyClassIndex())) {
			if (travelClassObjectY != null){
				classesForFlight.push(travelClassObjectY);	
			}
		}
		if (determineBooleanValueFromMatrixItem(matrixItem, dataContainer.getPremiumClassIndex())) {
			if (travelClassObjectP != null){
				classesForFlight.push(travelClassObjectP);	
			}
		}
		if (determineBooleanValueFromMatrixItem(matrixItem, dataContainer.getBusinessClassIndex())) {
			if (travelClassObjectJ != null){
				classesForFlight.push(travelClassObjectJ);	
			}
		}
		if (determineBooleanValueFromMatrixItem(matrixItem, dataContainer.getFirstClassIndex())) {
			if (travelClassObjectF != null){
				classesForFlight.push(travelClassObjectF);	
			}
		}
	}
	
	return classesForFlight;
}


// Create the internal pad prototype
String.prototype._pad = function(width,padChar,side) {
	var str = [side ? "" : this, side ? this : ""];
	while (str[side].length < (width ? width : 0)
		&& (str[side] = str[1] +(padChar ? padChar : " ")+str[0] ));
	return str[side];
}

// Create pad functions for general use
// "width" is the total width to pad to,
// "padChar" is the optional pad character -- default " "
String.prototype.padLeft = function(width,padChar) {
	return this._pad(width,padChar,0) };
String.prototype.padRight = function(width,padChar) {
	return this._pad(width,padChar,1) };
Number.prototype.padLeft = function(width,padChar) {
	return (""+this).padLeft(width,padChar) };
Number.prototype.padRight = function(width,padChar) {
	return (""+this).padRight(width,padChar) };

  
function arrivalCheckforMajorCities(data)
{
	departurePort =	$j($j('.predictiveTextField')[0]).parent().find('input[type=hidden]').val();
	arrivalPort = $j($j('.predictiveTextField')[1]).parent().find('input[type=hidden]').val();
																						   
	var majorAirports = data;
	var isArrivalMajor = false;
	var isDepartureMajor = false;
	
	for (i = 0; i < majorAirports.length; i++)
	{
		if ( majorAirports[i]  == departurePort)
		{
			isDepartureMajor  = true;
		}
		
		if (majorAirports[i] == arrivalPort)
		{
			isArrivalMajor = true;
		}
	}
	
	var instance = document.getElementById('instanceLabel');
	
	if (instance)
	{
		instance=instance.value
	}
	else
	{
		instance="";
	}
	
	instance = instance + 'depHour';
	
	if (isDepartureMajor && isArrivalMajor)
	{
		$j('.majorCitySelected').show();
	}
	else
	{
		$j('.majorCitySelected').hide();
	}
	
}

