//functions for interacting with the backend


//definitions of callbacks from the "generic" portion
var _galaxyHandlers = new Object();
_galaxyHandlers.galaxyPollExceptionHandler = null;
_galaxyHandlers.postGuiConnectedHandler = null;
_galaxyHandlers.initGalaxyHandler = null;
_galaxyHandlers.onLoadHandler = onLoadHandler; 
_galaxyHandlers.onUnloadHandler = null; 
_galaxyHandlers.responseHandler = handleResponse;
_galaxyHandlers.playingHandler = null;
_galaxyHandlers.layoutHandler = layoutHandler;
_galaxyHandlers.inputTypingHandler = null;
_galaxyHandlers.typedInputSentHandler = null;
_galaxyHandlers.nbestDropDownActivated = null;
_galaxyHandlers.nbestTokenDropDownActivated = null;
_galaxyHandlers.newNbest = null;

//_wamiHandlers.onBeforeUnloadHandler = onBeforeUnloadHandler;
_galaxyHandlers.onBeforeUnloadHandler = onBeforeUnloadHandler;
var COLORED = "";

function onBeforeUnloadHandler() {
    stopPolling();
    postXML("<?xml version='1.0' encoding='UTF-8'?><update stoppolling='true' />");
}

function onLoadHandler() {
	sendUserInfo();
	sendBrowserInfo();
}

// appended to the filename flightbrowser.css to prevent caching
var r = "?r=" + new Date().getTime();

// see attributeNames.js for the array attributeNames

// see head_includes.jsp for AUTO_ENROLL, UPDATE_PARTIALS, UPDATE_DISCOURSE

// see xmlscripts.js for the following functions
// sortFlights, sortFlightsBy, hideHelpBox, sendPassCode, formFieldRecord, 
// formFieldClick, formHighlightClear, flightClick, flightHover, changeRowColor, 
// sendPartialNL, sendNLFocusAttribute, formFieldTypedInput, autoEnroll, 
// clearTables, clearItinerary, sendBrowserInfo, xmlToString, clickItineraryHeader

var DISPLAY_OLD = 0;
var DISPLAY_NEW = 1;
var DISPLAY_PARSED = 2;


var sourceText = "";
var destText = "";
var dateText = "";
var timeText = "";
var airlineText = "";

var hasArrival = false;
var hasDeparture = false;
var hasDate = false;

function updateForm(attr_name, attr_value, display_type) {
    if (attr_value == "*CLEAR*") {

    	sourceText = destText = dateText= timeText = airlineText = "";
    	attr_value = null;
    	
    	
     } 
    
    // if user is not typing in this particular field at the moment
    var headElem = document.getElementById("headerText");
    
    if (_iPhone){
	    select = document.getElementById("dropdown");
		select.style.display = 'inline';
		select.style.visibility = 'visible';
    }
    if (!(userIsTyping&&"field_"+attr_name==lastEditedTextField)) {
	    if (attr_value!=null && display_type==DISPLAY_NEW) {
			var formElem = 
			    document.getElementById("field_" + attr_name);

			formElem.value = attr_value;
			var appendMobile = "";
			if (_iPhone){
				if (attr_name == 'source' && attr_value != ""){
					hasDeparture = true;
					sourceText = "from <a href='javascript:formFieldClick(topbutton_source)' id='toplink_source'>" + attr_value + "</a> ";
				}
				else if (attr_name == 'destination' && attr_value != ""){
					hasArrival = true;
					destText = "to <a href='javascript:formFieldClick(topbutton_destination)' id='toplink_destination'>" + attr_value + "</a> ";
				}
				else if (attr_name=='date' && attr_value.split(' ').length == 3) {
					
					var split = attr_value.split(' ');
					var just_date = split[1] + ' ' + split[2];
					dateText = "on <a href='javascript:formFieldClick(topbutton_date)' id='toplink_date'>" + just_date + "</a> ";
				}
				else if (attr_name == 'date' && attr_value != ""){
					hasDate = true;
					dateText = "on <a href='javascript:formFieldClick(topbutton_date)' id='toplink_date'>" + attr_value + "</a> ";
				}
				else if (attr_name == 'time' && attr_value != ""){
					timeText = "<a href='javascript:formFieldClick(topbutton_time)' id='toplink_time'>" + attr_value + "</a> ";
				}
				else if (attr_name == 'airline' && attr_value != ""){
					airlineText = "on <a href='javascript:formFieldClick(topbutton_airline)' id='toplink_airline'>" + attr_value + "</a> ";
				}
				finalString = sourceText + destText + dateText + timeText + airlineText + "<br><br>";
				headElem.style.textAlign='center';
				headElem.innerHTML = finalString.substring(0,1).toUpperCase() + 
					finalString.substring(1,finalString.length);	
				
				if (!hasArrival){
					headElem.innerHTML += "<strong>What is the arrival city?</strong><br>";
				}
				if (!hasDeparture){
					headElem.innerHTML += "<strong>What is the departure city?</strong><br>";
				}
				if (!hasDate){
					headElem.innerHTML += "<strong>What is the departure date?</strong><br>";
				}
				
				appendMobile = "Mobile";
				

			}
			
			formElem.className = "formFieldNew"+appendMobile;
			//formElem.style.backgroundColor = "#cc0000";
			//formElem.style.color = "#ffffff";
		} else if (attr_value!=null && display_type==DISPLAY_OLD) {
			var formElem = 
			    document.getElementById("field_" + attr_name);
			formElem.value = attr_value;
			var appendMobile = "";
			var appendMobile = "";
			if (_iPhone){
				if (attr_name == 'source' && attr_value != ""){
					hasDeparture = true;
					sourceText = "from <a href='javascript:formFieldClick(topbutton_source)' id='toplink_source'>" + attr_value + "</a> ";
				}
				else if (attr_name == 'destination' && attr_value != ""){
					hasArrival = true;
					destText = "to <a href='javascript:formFieldClick(topbutton_destination)' id='toplink_destination'>" + attr_value + "</a> ";
				}
				else if (attr_name=='date' && attr_value.split(' ').length == 3) {
					var split = attr_value.split(' ');
					var just_date = split[1] + ' ' + split[2];
					dateText = "on <a href='javascript:formFieldClick(topbutton_date)' id='toplink_date'>" + just_date + "</a> ";
				}
				else if (attr_name == 'date' && attr_value != ""){
					hasDate = true;
					dateText = "on <a href='javascript:formFieldClick(topbutton_date)' id='toplink_date'>" + attr_value + "</a> ";
				}
				else if (attr_name == 'time' && attr_value != ""){
					timeText = "<a href='javascript:formFieldClick(topbutton_time)' id='toplink_time'>" + attr_value + "</a> ";
				}
				else if (attr_name == 'airline' && attr_value != ""){
					airlineText = "on <a href='javascript:formFieldClick(topbutton_airline)' id='toplink_airline'>" + attr_value + "</a> ";
				}
				finalString = sourceText + destText + dateText + timeText + airlineText + "<br><br>";
				headElem.style.textAlign='center';
				headElem.innerHTML = finalString.substring(0,1).toUpperCase() + 
					finalString.substring(1,finalString.length);
				if (!hasArrival){
					headElem.innerHTML += "<strong>What is the arrival city?</strong><br>";
				}
				if (!hasDeparture){
					headElem.innerHTML += "<strong>What is the departure city?</strong><br>";
				}
				if (!hasDate){
					headElem.innerHTML += "<strong>What is the departure date?</strong><br>";
				}
			}
			formElem.className = "formFieldOld"+appendMobile;
			
			
		} else if (attr_value!=null && display_type==DISPLAY_PARSED) {
			var formElem = 
				document.getElementById("field_" + attr_name);
			formElem.value = attr_value;
			var appendMobile = "";
			if (_iPhone){
				if (attr_name == 'source' && attr_value != ""){
					hasDeparture = true;
					sourceText = "from <a href='javascript:formFieldClick(topbutton_source)' id='toplink_source'>" + attr_value + "</a> ";
				}
				else if (attr_name == 'destination' && attr_value != ""){
					hasArrival = true;
					destText = "to <a href='javascript:formFieldClick(topbutton_destination)' id='toplink_destination'>" + attr_value + "</a> ";
				}
				else if (attr_name=='date' && attr_value.split(' ').length == 3) {
					var split = attr_value.split(' ');
					var just_date = split[1] + ' ' + split[2];
					dateText = "on <a href='javascript:formFieldClick(topbutton_date)' id='toplink_date'>" + just_date + "</a> ";
				}
				else if (attr_name == 'date' && attr_value != ""){
					hasDate = true;
					dateText = "on <a href='javascript:formFieldClick(topbutton_date)' id='toplink_date'>" + attr_value + "</a> ";
				}
				else if (attr_name == 'time' && attr_value != ""){
					timeText = "<a href='javascript:formFieldClick(topbutton_time)' id='toplink_time'>" + attr_value + "</a> ";
				}
				else if (attr_name == 'airline' && attr_value != ""){
					airlineText = "on <a href='javascript:formFieldClick(topbutton_airline)' id='toplink_airline'>" + attr_value + "</a> ";
				}
				finalString = sourceText + destText + dateText + timeText + airlineText + "<br><br>";
				headElem.style.textAlign='center';
				headElem.innerHTML = finalString.substring(0,1).toUpperCase() + 
					finalString.substring(1,finalString.length);
				if (!hasArrival){
					headElem.innerHTML += "<strong>What is the arrival city?</strong><br>";
				}
				if (!hasDeparture){
					headElem.innerHTML += "<strong>What is the departure city?</strong><br>";
				}
				if (!hasDate){
					headElem.innerHTML += "<strong>What is the departure date?</strong><br>";
				}

			}
			formElem.className = "formFieldParsed"+appendMobile;
			//formElem.style.backgroundColor = "#008800";
			//formElem.style.color = "#ffffff";
		} else { //if attribute value is null, don't do anything
		}
	}
}
    

function handleResponse(replyNode) {
	try {
		var replyType = replyNode.getAttribute("type");
		
		if(replyType == "timeout") {
			handleTimeout(replyNode);
		} else if (replyType == "html") {
			// ignore html strings from Mercury
		} else if (replyType == "focus_attr_start_recording") {		
			var audioApplet = document.getElementById("AudioApplet");
			audioApplet.setRecordEnabled(true);
		} else if (replyType == "html_flight_data") {
			handleFlightData(replyNode);
	    } else if (replyType == "html_itinerary_data") {
	    	handleItineraryData(replyNode, true);
	    } else if (replyType == "nbest_alternatives"){
	    	handleNbestData(replyNode);
	    } else if (replyType == "html_partial_itinerary_data") {
	    	handleItineraryData(replyNode, false);
	    } else if (replyType == "need_return_date") {
	    	clearTables();
	    } else if (replyType == "history_cleared") {
	    	clearTables();
	    	clearItinerary();
	    	clearTopNav();
	    	if (_iPhone){
	    		clearNBest();
	    	}
	    	
	    	// clearform
	    } else if (replyType == "scratched") {
	   		clearTables();
	   		if (_iPhone){
	   			clearNBest();
	   		}
	    } else if (replyType == "paraphrase_string_received") {
	    	formHighlightClear();
	    	changeRowColor(null);		
	    } else if (replyType == "welcome_message") {
	    	if (AUTO_ENROLL) {autoEnroll();} 
		} else if (replyType == "form_updates_discourse_old") {
		    // clear all fields first
		    for (var i=0; i<attributeNames.length; i++) {
		    	updateForm(attributeNames[i], "", DISPLAY_OLD);
			}
   	    	    
		    for (var i=0; i<attributeNames.length; i++) {
		    	var value = replyNode.getAttribute(attributeNames[i]);
				updateForm(attributeNames[i], value, DISPLAY_OLD);
				
			}
		} else if (UPDATE_DISCOURSE && replyType == "form_updates_discourse_parsed") {
			for (var i=0; i<attributeNames.length; i++) {
		    	var value = replyNode.getAttribute(attributeNames[i]);
				updateForm(attributeNames[i], value, DISPLAY_PARSED);
			}
		} else if ( UPDATE_PARTIALS && 
		              ((replyType == "form_updates_partial") ||
		               (replyType == "form_updates_discourse_new")) ) {       
			var updateTrue = false;
			var values = new Array();    
		    	    
		    for (var i=0; i<attributeNames.length; i++) {
		    	var value = replyNode.getAttribute(attributeNames[i]);
				values[i] = value;
				updateTrue = updateTrue || (value != null);
			}
			
			if (updateTrue) {
				for (var i=0; i<attributeNames.length; i++) {
					updateForm(attributeNames[i], values[i], DISPLAY_NEW);
				}
			}
		} else if (replyType == "form_clear") {
			for (var i=0; i<attributeNames.length; i++) {
		    	updateForm(attributeNames[i], "", DISPLAY_OLD);
			}
		} else if(replyType == "eval") {
			//eval(replyNode.getAttribute("script"));
		} else {
			return genericHandleResponse(replyNode); //delegate everything else
		}
	} catch(e) {
		alert(e);
	}	
}

var colorIndex = 0;
colorList = new Array("#080", "#088", "#08F", "#88F", "#F8F", "#F88", "#F80", "#F40", "#C00", "#800", "#FFF")
var airlineColors = new Array();
function getAirlineColor(airline) {
	if (!airlineColors[airline]) {
		airlineColors[airline] = colorList[colorIndex];
		colorIndex = (colorIndex == colorList.length-1) ? 0 : colorIndex + 1;
	}
	return airlineColors[airline];
}

function getColored(){
	return COLORED
}

function setColored(str){
	COLORED = str;
}

function handleNbestData(replyNode) {
	if (_iPhone){
		COLORED = "";
		
		var output = new Array();
		var nbestData = new Array();
		nbestData = replyNode.getElementsByTagName("nbest_data");
	
		for (var i=0; i<5;i++){
			var candidates = new Array();
			
			if (nbestData[i]!=undefined){
				candidates = nbestData[i].getAttribute("candidate"+i);
				output.push(candidates);
			}
		}
		if (output.length>1){
			addNBest(output);
		}
	}
}

function handleItineraryData(replyNode, isFinal) {
	hasArrival = false;
	hasDeparture = false;
	hasDate = false;
	
	var testData = new Array();
	testData = replyNode.getElementsByTagName("flight_data");
	
	var documentOutput = "";
	var finalItinOutput = "";
	
	//final itinerary
	if (isFinal) {
		//finalItinOutput += "<table width="+tableWidth+"><tr><h1><font color='#c6710e'>Itinerary</font></h1></tr><tr>&nbsp;</tr>";
	    finalItinOutput += "<h1><font color='#c6710e'>Itinerary</font></h1><br/>";
	
	    for (var i=0;i<testData.length;i++) {
	    	var flightData = new Array();
	    	flightData = testData[i].getElementsByTagName("flight");
	    	
	    	for (var j=0;j<flightData.length;j++) {
		   		var flightNumber  = flightData[j].getAttribute("flight_number");
			    var airline       = flightData[j].getAttribute("airline");
			    var fromAirport   = flightData[j].getAttribute("from_airport");
			    var toAirport     = flightData[j].getAttribute("to_airport");
			    var departTimeStr = flightData[j].getAttribute("departDateString");
			    var arriveTimeStr = flightData[j].getAttribute("arriveDateString");
			    var aircraftType  = flightData[j].getAttribute("aircraft_type");
			    
			    /*
			    finalItinOutput += "<tr><b>"+fromAirport+" to "+toAirport+"</b></tr>" +
			    				  //"<tr><b>Airline:</b> "+airline+"</tr>" +
			    				  "<tr><b>Flight #:</b> "+flightNumber+"</tr>" +
			    				  "<tr><b>Airline:</b> "+airline+(abbreviations[airline]==""?"":" ("+abbreviations[airline]+")")+"</tr>" +
			    				  "<tr><b>From:</b> "+fromAirport+(abbreviations[fromAirport]==""?"":" ("+abbreviations[fromAirport]+")")+"</tr>" +
			    				  "<tr><b>To:</b> "+toAirport+(abbreviations[toAirport]==""?"":" ("+abbreviations[toAirport]+")")+"</tr>" +
			    			      "<tr><b>Departure Time:</b> "+departTimeStr+"</tr>" +
			    			      "<tr><b>Arrival Time:</b> "+arriveTimeStr+"</tr>" +
			    			      "<tr><b>Aircraft Type:</b> "+aircraftType+"</tr>" +
			    			      "<tr>&nbsp;</tr>";
			    */
			    
			    finalItinOutput += 
		                      "<div class='finalItinerary'><b>"+fromAirport+" to "+toAirport+" ("+airline+" "+flightNumber+")</b>" +
		    				  //"<span class='itineraryInfo' id='itineraryInfo"+i+"'>" +
		    				  	  "<br/><b>Flight #:</b> "+flightNumber +
		    				  	  "<br/><b>Airline:</b> "+airline+(abbreviations[airline]==""?"":" ("+abbreviations[airline]+")") +
		    				  	  "<br/><b>From:</b> "+fromAirport+(abbreviations[fromAirport]==""?"":" ("+abbreviations[fromAirport]+")") +
		    				  	  "<br/><b>To:</b> "+toAirport+(abbreviations[toAirport]==""?"":" ("+abbreviations[toAirport]+")") +
		    				  	  "<br/><b>Departure Time:</b> "+departTimeStr+
		    			      	  "<br/><b>Arrival Time:</b> "+arriveTimeStr+
		    			      	  "<br/><b>Aircraft Type:</b> "+aircraftType+
		    			      //"</span></span></a><br/><br/>";
		    			      "</div><br/><br/>";
			}
		}
		
		var totalPrice = replyNode.getAttribute("price");
		finalItinOutput += "<b>Total Price:</b> $" + totalPrice;
	} 
	
	// partial itinerary
	var mobileClass = ""
	for (var i=0;i<testData.length;i++) {
    	var flightData = new Array();
    	flightData = testData[i].getElementsByTagName("flight");
    	
    	
    	if (_iPhone){
    		mobileClass = " class = partialItineraryMobile ";
    	}
    	
    	for (var j=0;j<flightData.length;j++) {
	   		var flightNumber  = flightData[j].getAttribute("flight_number");
		    var airline       = flightData[j].getAttribute("airline");
		    var fromAirport   = flightData[j].getAttribute("from_airport");
		    var toAirport     = flightData[j].getAttribute("to_airport");
		    var departTimeStr = flightData[j].getAttribute("departDateString");
		    var arriveTimeStr = flightData[j].getAttribute("arriveDateString");
		    var aircraftType  = flightData[j].getAttribute("aircraft_type"); 
		    
		    documentOutput += "<a class='cursorChange'>" +
		                      "<span class='itineraryHeader' id='itineraryHeader"+i+"' ><b>"+fromAirport+" to "+toAirport+" ("+airline+" "+flightNumber+")</b>" +
		    				  "<span class='itineraryInfo' id='itineraryInfo"+i+"'><table>" +
		    				  	  "<tr" + mobileClass + "><td><b>Flight #:</b></td><td> "+flightNumber + "</td></tr>" +
		    				  	  "<tr" + mobileClass + "><td><b>Airline:</b></td><td> "+airline+(abbreviations[airline]==""?"":" ("+abbreviations[airline]+")") + "</td></tr>" +
		    				  	  "<tr" + mobileClass + "><td><b>From:</b></td><td> "+fromAirport+(abbreviations[fromAirport]==""?"":" ("+abbreviations[fromAirport]+")") + "</td></tr>" +
		    				  	  "<tr" + mobileClass + "><td><b>To:</b></td><td> "+toAirport+(abbreviations[toAirport]==""?"":" ("+abbreviations[toAirport]+")") + "</td></tr>" +
		    				  	  "<tr" + mobileClass + "><td><b>Departs:</b></td><td> "+departTimeStr+ "</td></tr>" +
		    			      	  "<tr" + mobileClass + "><td><b>Arrives:</b></td><td> "+arriveTimeStr+ "</td></tr>" +
		    			      	  "<tr" + mobileClass + "><td><b>Aircraft Type:</b></td><td> "+aircraftType+ "</td></tr>" +
		    			      "</table></span></span></a><br/><br/>";
		    			      
		    			      /*
		    			      "Flight #: " + flightNumbers[(k-1)/2] + "<br/>" +
  				                  "Airline: " + airlines[(k-1)/2] + (abbreviations[airlines[(k-1)/2]]=="" ? "" : " ("+abbreviations[airlines[(k-1)/2]]+")") + "<br/><br/>" +
  				                  "From: " + dests[(k-1)/2] + (abbreviations[dests[(k-1)/2]]=="" ? "" : " ("+abbreviations[dests[(k-1)/2]]+")") + "<br/>" +
  				                  "To: " + dests[(k+1)/2] + (abbreviations[dests[(k+1)/2]]=="" ? "" : " ("+abbreviations[dests[(k+1)/2]]+")") + "<br/><br/>" +
  				                  */			    			      
		    				  //"<tr><b>Airline:</b> "+airline+"</tr>" +
		    			      //"<tr><b>Flight #:</b> "+flightNumber+"</tr>" +
		    			      //"<tr>&nbsp;</tr>";
		}
    	
    	
		
	}
	
	if (isFinal) {
		document.getElementById("flightDisplay").style.display= 'inline';
		document.getElementById("flightDisplay").innerHTML = finalItinOutput;
		// document.getElementById("itineraryDisplay").innerHTML = documentOutput;
		clearItinerary();
		
		
		
		if (_iPhone){
	  		//document.getElementById("viewport").setAttribute('content','device-width = 480, initial-scale=.65, width = 980, minimum-scale = .5, maximum-scale = 1');
			
	  		clearNBest();
	  		document.getElementById("dropdown").style.display = 'none';
	  		document.getElementById("headerText").innerHTML = "Below is your itinerary. Say 'Start Over' " +
	  		"or 'Go Back' if you wish to change anything."
	  		window.scrollTo(0, 0);
    	}
	} else {
		
		document.getElementById("itineraryDisplay").innerHTML = documentOutput;
		document.getElementById("itineraryDisplay").style.display= 'inline';
		
		if (_iPhone){
			newNBest = ""
			headerT = document.getElementById("headerText");
			
			newNBest = headerT.innerHTML.split(' ').splice(0,4).join(' ');
			clearTopNav();
			updateForm("source", toAirport, DISPLAY_NEW);
			//updateForm("destination", fromAirport, DISPLAY_NEW);
			//returnFlightNBest(newNBest);
			headerT.innerHTML = "When will you be returning? <br><br>If this is not your final stop, what is your next destination?";
			//document.getElementById("viewport").setAttribute('content','device-width = 480, initial-scale=.7, width = 980, minimum-scale = .6, maximum-scale = 1');
			window.scrollTo(0, 0);
			
    	}
		
	}
}

// resizes the table width so that it fits on the screen,
// called when window is resized
function setTableWidth(frameWidth) {
	tableWidth = Math.max(frameWidth - 750, 250);
}

var tableWidth = 750;
var abbreviations = new Array();
var detailedInfo = new Array();
function handleFlightData(replyNode) {
	var rowHeight = 20;
	var cellpadding = 1;
	if (_iPhone){
		document.getElementById("dropdown").display = 'inline';
	}
		    
	var abbrevData = new Array();
	abbrevData = replyNode.getElementsByTagName("map_abbrev")[0].getElementsByTagName("abbrev");		    
	for (var j=0;j<abbrevData.length;j++) { 
		abbreviations[abbrevData[j].getAttribute("key")] = abbrevData[j].getAttribute("value");
	}
		    
    var testData = new Array();
    testData = replyNode.getElementsByTagName("flight_data");
		    
    var departTimeMin = Infinity;
	var arriveTimeMax = -Infinity;
		    
    for (var i=0;i<testData.length;i++) {
    	var flightData = new Array();
    	flightData = testData[i].getElementsByTagName("flight");
    	
    	for (var j=0;j<flightData.length;j++) {
	   		var departTime   = flightData[j].getAttribute("departDate");
	    	var arriveTime   = flightData[j].getAttribute("arriveDate");
		        
	   		departTimeMin = Math.min(departTimeMin, parseInt(departTime));
			arriveTimeMax = Math.max(arriveTimeMax, parseInt(arriveTime));
		}
	}
		    
    // divide tableWidth by the number of milliseconds between the 
    // earliest departure and latest arrival
	var scale_factor = tableWidth / (arriveTimeMax - departTimeMin);
	
	markTime = 360     // 3600000 milliseconds per hour / 10000
	hourMarkMin = Math.floor(departTimeMin / markTime) + 1;
	hourMarkMax = Math.floor(arriveTimeMax / markTime);

	var prevHourMark = 0;
	var totalHeight = (testData.length + 1) * (rowHeight + cellpadding*2 + 2);
	var hourMarks = "";
	
	//var hourMarks = "<span class='hourMark' style='left:" + 
	//                "0px;height:" + totalHeight + "px'>" +
	//                "<span class='localTimes' style='left:0px'>"+
	//                "&nbsp;<br/>&nbsp;</span>";
	for	(var h=hourMarkMin; h<=hourMarkMax; h++) {
		currHourMark = Math.round((h*markTime - departTimeMin)*scale_factor);
		var currWidth = currHourMark-prevHourMark
		
		var dep_offset = flightData[0].getAttribute("doffset")
		var arr_offset = flightData[flightData.length-1].getAttribute("aoffset")
		
		var doffsetsign  = parseInt(dep_offset.substring(0,1)+"1"); 
		var doffsethours = parseInt(dep_offset.charAt(1)=="0" ? 
									dep_offset.substring(2,3) : dep_offset.substring(1,3));
		var doffsetmins  = parseInt(dep_offset.charAt(3)=="0" ?
									dep_offset.substring(4,5) : dep_offset.substring(3,5));
		
		var aoffsetsign  = parseInt(arr_offset.substring(0,1)+"1");
		var aoffsethours = parseInt(arr_offset.charAt(1)=="0" ? 
									arr_offset.substring(2,3) : arr_offset.substring(1,3));
		var aoffsetmins  = parseInt(arr_offset.charAt(3)=="0" ?
									arr_offset.substring(4,5) : arr_offset.substring(3,5));
		
		var gmtTime = h*markTime;
		var departLocalTime = gmtTime+doffsetsign*(360*doffsethours + 6*doffsetmins);
		var arriveLocalTime = gmtTime+aoffsetsign*(360*aoffsethours + 6*aoffsetmins);
		
		var gmtHours		 = (Math.floor(gmtTime/360)) % 24;
		var gmtMins          = Math.floor(gmtTime/6) % 60;
		var departLocalHours = Math.floor(departLocalTime/360) % 24;
		var departLocalMins  = Math.floor(departLocalTime/6) % 60;
		var arriveLocalHours = Math.floor(arriveLocalTime/360) % 24;
		var arriveLocalMins  = Math.floor(arriveLocalTime/6) % 60;
		
		
		/* debugging
		if (h==hourMarkMin) {
			//alert(gmtTime+" "+departLocalTime+" "+arriveLocalTime);
			alert(departLocalHours+" "+departLocalMins+"\n"+
			      arriveLocalHours+" "+arriveLocalMins+"\n"+
			      gmtHours+" "+gmtMins+"\n"+
			      dep_offset+" "+doffsetsign+" "+doffsethours+" "+doffsetmins+"\n"+
			      arr_offset+" "+aoffsetsign+" "+aoffsethours+" "+aoffsetmins+"\n");
		}  */
		
		// if the hours are already spaced far enough apart, label every hour
		// or if they are not spaced far enough apart, label every two hours
		// (avoids overlapping hour labels)
		if (scale_factor >= 0.13 || h % 2 == 0) {
		    hourMarks += "<span class='hourMark' style='left:" + 
		                 currWidth + "px;height:" + totalHeight + "px' />" +
		                 "<span class='localTimes' style='left:0px'>"+
		                 "<span class='source_city'>"+formatTime(departLocalHours,departLocalMins)+"</span><br/>"+
		                 "<span class='destination_city'>"+formatTime(arriveLocalHours,arriveLocalMins)+"</span></span>";
		} else {
			hourMarks += "<span class='hourMark' style='left:" + 
		                 currWidth + "px;height:" + totalHeight + "px' />" +
		                 "<span class='localTimes' style='left:0px'>"+
		                 "&nbsp;<br/>&nbsp;</span>";
		}
	    prevHourMark = currHourMark;
	}
	//var currWidth = tableWidth - currHourMark;
	//hourMarks += "<span class='hourMark' style='left:" + 
	//             currWidth + "px;height:" + totalHeight + "px' />" +
	//	         "<span class='localTimes' style='left:0px'>"+
	//	         "&nbsp;<br/>&nbsp;</span>";
	
	var testHourMarks = "<span class='hourMark' style='top:0px;left:0px;height:500px' />";
	
	var tableClass;
	if (!_iPhone){
		tableClass = 'sortByLabel'
	}
	else{
		tableClass = 'sortByLabelMobile'
	}
	
	
	if (!_iPhone){
		var documentOutput = "<table bgcolor='#cccccc' cellpadding="+cellpadding+" border=0><br />\n";
	}
	else{
		var documentOutput = "<table bgcolor='#ffffff' cellpadding="+cellpadding+" border=0>";
	}
	
	documentOutput += "<tr>\n";
	
	
	if (!_iPhone){
		documentOutput += 
		"<td class='" + tableClass+ "'>Sort By:</td>" +
		"<td class='" + tableClass + "2'><a class='cursorChange' onclick=sortFlightsBy('price_asc')> Price </a></td>\n" +
		  "<td class='" + tableClass + "2'><a class='cursorChange' onclick=sortFlightsBy('num_stops_asc')> Stops </a></td>\n" +
		  "<td class='" + tableClass + "2'><a class='cursorChange' onclick=sortFlightsBy('dep_time_asc')>Depart</a></td>\n" +
		  "<td class='" + tableClass + "2'><a class='cursorChange' onclick=sortFlightsBy('arr_time_asc')> Arrival </a></td>\n";
	}
	else{
		documentOutput +=
			  "<td width=80px></td><td width=80px></td><td width=80px></td><td class='" + tableClass+ "' align=right>Also Sort By:</td>";
	}
		documentOutput += 
			  "<td class='" + tableClass + "2'><a class='cursorChange' onclick=sortFlightsBy('duration_asc')> Duration </a></td>\n";
	if (!_iPhone){
		documentOutput += "<tr></table><br />\n";
	}
	else{
		documentOutput += "<tr></table>\n";
	}
		
		    
    
	
	var flightTableId = "flightTable";
	if (_iPhone){
		flightTableId = 'flightTableMobile';
	}
	
	// string that will be written 
	documentOutput += 
	          "<center><table id='" + flightTableId + "'>\n" +
	          "<tr>\n";
	          
	if (_iPhone){
		documentOutput +=      
			  "<td class=table_heading_link align=center><a class='cursorChange' onclick=sortFlightsBy('price_asc')> Price </a></td>\n" +
			  "<td class=table_heading_link align=center><a class='cursorChange' onclick=sortFlightsBy('airline_code_asc')> Airline </a></td>\n" +
	          "<td class=table_heading_link align=center><a class='cursorChange' onclick=sortFlightsBy('dep_time_asc')>Depart</a></td>\n" +
	          "<td class=table_heading_link align=center><a class='cursorChange' onclick=sortFlightsBy('arr_time_asc')>Arrive</a></td>\n" +
	          "<td class=table_heading_link align=center><a class='cursorChange' onclick=sortFlightsBy('num_stops_asc')> Stops </a></td>\n";
	          }
	else{
		documentOutput += 
			"<td class=table_heading align=center>Price</td>\n" +
	          "<td class=table_heading align=center>Stops</td>\n" +
				"<td class=table_heading align=center>From</td>\n" +
	            "<td class=table_heading align=center>To</td>\n" +
	            "<td class='hourMark'"+(navigator.appName=="Microsoft Internet Explorer"?" style='position:relative'":"")+">" + hourMarks + "</td>\n" +
	            "<td><img border=0 src='images/1x1images/1x1transparent.gif' height="+rowHeight+" width=50>" +
	            "</td>";
	}
	documentOutput += 
			"</tr>";
		    
	var startDest;
	var endDest;
	var offsets = new Array(2);
		
	for (var i=0;i<testData.length;i++) {
		var flightData = new Array();
    	flightData = testData[i].getElementsByTagName("flight");
    	var price = testData[i].getAttribute("price");
    	var totalDuration = testData[i].getAttribute("tduration");
    	if (price == "N/A") {price = "";}  
    	
    	var imageWidth = new Array();
    	var startTime = departTimeMin;
    	var imageIndex = 0; 
    	
    	// Array of all destinations of a trip
    	// For example, if the trip is a flight from Boston to Miami, connecting at JFK
    	// then the array is {BOS, JFK, MIA}
    	var dests = new Array();
		var destsIndex = 0;
		
		var departTimes = new Array();
		var arriveTimes = new Array();
		var flightNumbers = new Array();
    	var segDuration = new Array();
    	var airlines = new Array();
    	var aircraftTypes = new Array();
    	
    	for (var j=0;j<flightData.length;j++) {
		    var flightNumber  = flightData[j].getAttribute("flight_number");
		    var aircraftType  = flightData[j].getAttribute("aircraft_type");
		    var airline       = flightData[j].getAttribute("airline");
		    var fromAirport   = flightData[j].getAttribute("from_airport");
		    var toAirport     = flightData[j].getAttribute("to_airport");
		    var departTimeStr = flightData[j].getAttribute("departDateString");
		    var arriveTimeStr = flightData[j].getAttribute("arriveDateString");
		    var departTime    = flightData[j].getAttribute("departDate");
		    var arriveTime    = flightData[j].getAttribute("arriveDate");
		    var fduration     = flightData[j].getAttribute("fduration");
		    var lduration     = flightData[j].getAttribute("lduration");
			
			segDuration[2*j+1] = fduration;
			segDuration[2*j+2] = lduration;
			
			departTimes[destsIndex] = departTimeStr;
			arriveTimes[destsIndex] = arriveTimeStr;
			flightNumbers[destsIndex] = flightNumber;
			airlines[destsIndex] = airline;
			aircraftTypes[destsIndex] = aircraftType;
			dests[destsIndex++] = fromAirport;
			        
			// final destination
			if(j == flightData.length - 1) {
				dests[destsIndex] = toAirport;
			}
        	
        	var depart_pixel = Math.round((parseInt(departTime)-startTime)*scale_factor);
        	var arrive_pixel = Math.round((parseInt(arriveTime)-parseInt(departTime))*scale_factor); 
        	var end_pixel = Math.round((arriveTimeMax-parseInt(arriveTime))*scale_factor);
        	
        	imageWidth[imageIndex++] = depart_pixel;
        	imageWidth[imageIndex++] = arrive_pixel;
        	imageWidth[imageIndex] = end_pixel;
		    startTime = arriveTime;
    	}
    	
    	startDest = dests[0];
    	endDest = dests[dests.length-1];
    	
    	var stops_string = "";
    	if (dests.length == 2) { // nonstop flight
    		stops_string = "(none)";
    	} else if (dests.length > 2) {
    		var destNum = 1;
    		while (destNum < dests.length-2) {
    			stops_string += "<span title=\""+abbreviations[dests[destNum]]+"\">"+dests[destNum++] + "</span>, ";
    		}
    		//stops_string += dests[destNum++];
    		stops_string += "<span title=\""+abbreviations[dests[destNum]]+"\">"+dests[destNum++] + "</span>";
    	}
    	
    	var airlinesArray = new Array();
    	var airlines_string = "";
    	for (var q=0; q<airlines.length-2; q++){
    		airlines_string += airlines[q] + ", ";
    	}
    	airlines_string += airlines[q];
    	
    	var splitDepart = departTimes[0].split(' ');
    	var splitArrive = arriveTimes[arriveTimes.length-1].split(' ');
    	var flightTableClass;
    	if (!_iPhone) {
    		flightTableClass = "";
    	}
    	else{
    		if (i%2==0){
    			flightTableClass = "class = flightTableMobileEven";
    		}
    		else{
    			flightTableClass = "class = flightTableMobileOdd";
    		}
    	}
    	
    	
    	
    	
    	detailedInfo[i]="";
    	for(var k=0;k<imageWidth.length;k++) {
    		if (k % 2 == 1) {
	    		detailedInfo[i] +=
	    				  "<table><tr><td>Flight #:</td><td>" + flightNumbers[(k-1)/2] + "<br/></td></tr>" +
		                  "<tr><td>Airline:</td><td>" + airlines[(k-1)/2] + (abbreviations[airlines[(k-1)/2]]=="" ? "" : " ("+abbreviations[airlines[(k-1)/2]]+")") + "<br/></td></tr>" +
		                  "<tr><td>From:</td><td>" + dests[(k-1)/2] + (abbreviations[dests[(k-1)/2]]=="" ? "" : " ("+abbreviations[dests[(k-1)/2]]+")") + "<br/></td></tr>" +
		                  "<tr><td>To:</td><td>" + dests[(k+1)/2] + (abbreviations[dests[(k+1)/2]]=="" ? "" : " ("+abbreviations[dests[(k+1)/2]]+")") + "<br/></td></tr>" + 
		                  "<tr><td>Departure:</td><td>" + departTimes[(k-1)/2] + "<br/></td></tr>" +
		                  "<tr><td>Arrival:</td><td>" + arriveTimes[(k-1)/2] + "<br/></td></tr>" +
		                  "<tr><td>Aircraft Type:</td><td>" + aircraftTypes[(k-1)/2] + "<br/></td></tr>" +
						  "<tr><td>Flight Duration:</td><td>" + segDuration[k] + "<br/></td></tr>" +
						  "<tr><td>Total Trip Duration:</td><td>" + totalDuration + "<br/></td></tr></table>";
	    		if (k+2<imageWidth.length){
	    			detailedInfo[i] += "<hr>"
	    		}
    		}
    		
    	}
    	
    	
	    documentOutput += "<tr " + flightTableClass+ " onclick='javascript:flightClick("+i+",null,null);'>\n";
            
            
        if (_iPhone){
        	documentOutput += 
        		"<td " + flightTableClass + " align=center><a name='row" + i + "'></a> " + price.slice(0,-3) + "</td>\n" + 
        		"<td " + flightTableClass + " align=center>" + airlines_string + "</td>\n" + 
	            "<td " + flightTableClass + " align=center>" + splitDepart[1].slice(0,-1) + "</td>\n" +
	            "<td " + flightTableClass + " align=center>" + splitArrive[1].slice(0,-1) + "</td>\n" +
	            "<td " + flightTableClass + " align=center>" + stops_string + "</td>\n";
        }
        else{
	    	documentOutput += 
	    		"<td " + flightTableClass + " align=center><a name='row" + i + "'></a> " + price + "</td>\n" +
	    		"<td " + flightTableClass + " align=center>" + stops_string + "</td>\n" +
            "<td align=center class='source_city' title=\""+abbreviations[startDest]+"\">" + startDest + "</td>\n" +
            "<td align=center class='destination_city' title=\""+abbreviations[endDest]+"\">" + endDest + "</td>\n"+
            "<td align=center>";
	    	
	    }
   		
	    
	    var color = "transparent";
	    var tooltipContents;
	    var airlineContents;
	    // empty,flight,stop,flight,...,stop,flight,empty
	    if (!_iPhone){
	   		for(var k=0;k<imageWidth.length;k++) {
	   			if (k == 0 || k == imageWidth.length - 1) {
	   				color = "transparent";
	   				tooltipContents = "";
	   				airlineText = "";
	   			} else if (k % 2 == 1) {
	   				//color = getAirlineColor(airline);
	   				color = getAirlineColor(airlines[(k-1)/2]);
	   		
	   				tooltipContents = "<span class='tooltip'>" +
	   				                  //"Airline: " + airline + "<br/>" +
	   				                  "Flight #: " + flightNumbers[(k-1)/2] + "<br/>" +
	   				                  "Airline: " + airlines[(k-1)/2] + (abbreviations[airlines[(k-1)/2]]=="" ? "" : " ("+abbreviations[airlines[(k-1)/2]]+")") + "<br/><br/>" +
	   				                  "From: " + dests[(k-1)/2] + (abbreviations[dests[(k-1)/2]]=="" ? "" : " ("+abbreviations[dests[(k-1)/2]]+")") + "<br/>" +
	   				                  "To: " + dests[(k+1)/2] + (abbreviations[dests[(k+1)/2]]=="" ? "" : " ("+abbreviations[dests[(k+1)/2]]+")") + "<br/><br/>" + 
	   				                  "Departure: " + departTimes[(k-1)/2] + "<br/>" +
	   				                  "Arrival: " + arriveTimes[(k-1)/2] + "<br/><br/>" +
	   				                  "Aircraft Type: " + aircraftTypes[(k-1)/2] + "<br/><br/>" +
	   								  "Flight Duration: " + segDuration[k] + "<br/>" +
	   								  "Total Trip Duration: " + totalDuration + "<br/>" +
	   								  "</span>";
	   				airlineText = "<span class='airlineText' style='height:" + rowHeight + 
	                              ";width:" + imageWidth[k] + ";background-color:" + color + 
	                              "' onClick='flightClick("+i+","+k+",false)' onmouseover='flightHover("+i+","+k+",true)'" +
	                              " onmouseout='flightHover("+i+","+k+",false)' ondblclick='flightClick("+i+","+k+",true)'>" + 
	                              airlines[(k-1)/2] + "</span>";
	   			} else {
	   				//color = "gray"
	   				color = "#888"
	   				tooltipContents = "<span class='tooltip'>" +
	   								  "Airport: " + dests[k/2] + (abbreviations[dests[k/2]]=="" ? "" : " ("+abbreviations[dests[k/2]]+")") + "<br/><br/>" + 
	   								  "Layover Duration: " + segDuration[k] + "<br/>" +
	   								  "Total Trip Duration: " + totalDuration + "<br/>" +
	   								  "</span>";
	   				airlineText = "<span class='airlineText' style='height:" + rowHeight + 
	                              ";width:" + imageWidth[k] + ";background-color:" + color + 
	                              "' onClick='flightClick("+i+","+k+",false)' onmouseover='flightHover("+i+","+k+",true)'" +
	                              " onmouseout='flightHover("+i+","+k+",false)' ondblclick='flightClick("+i+","+k+",true)'>" + 
	                              (imageWidth[k]>30?dests[k/2]:"") + "</span>";
	   			}
	            
	            documentOutput += "<a class='segmentInfo'><img border=0 src='images/1x1images/1x1transparent.gif' height=" 
	                              + rowHeight + " width=" + imageWidth[k] + ">" + airlineText + tooltipContents + "</a>";
	        }
	        documentOutput += "</td>\n" +
        				  "<td></td>\n"+
 			              "</tr>\n";
	    }
        
        
	}
    documentOutput += "</table></center>";
    
    //abortAudio(); 
    document.getElementById("flightDisplay").style.display= 'inline';
  	document.getElementById("flightDisplay").innerHTML = documentOutput;
  	
  	// Scrolls to relevant part of screen when on iPhone and resizes the zoom.
  	if (_iPhone) {
  		//document.getElementById("viewport").setAttribute('content','device-width = 320, initial-scale=.75, width = 480, minimum-scale = .75, maximum-scale = 1.6, user-scalable=1');
  		// window.scrollTo(0, 185);
  		document.getElementById('instructions').style.display = 'none';
  		
  	}
  	
}	

function getDetailedInfo(index){
	return detailedInfo[index];
}
		    
function formatTime(hours, mins) {
	var formattedTime;

	if (mins<=10) {
		mins = "0"+mins;
	}
	
	if (hours==0) {
		formattedTime = "12:"+mins+"am";
	} else if (hours==12) {
		formattedTime = "12:"+mins+"pm";
	} else if (hours>12) {
		pm_hours = hours - 12;
		formattedTime = pm_hours+":"+mins+"pm";
	} else {
		formattedTime = hours+":"+mins+"am";
	}
	
	return formattedTime;
}		    
		    
function handleTimeout(replyNode) {	
	setSendButtonDisabled(true);
	
	var timeoutText = "Session Timed Out</h1><p>" + 
			   "Click the browser's <b> reload </b> button to restart.";
	
	document.getElementById("flightDisplay").innerHTML = timeoutText;
}
