function generateXMLRequest()
{
// Build the XML Requester
var d = new Date();
var dtime = d.getTime() - (d.getTime() % 3000);
var xmlreq = GXmlHttp.create();
xmlreq.open('get', 'acars_map.ws?time=' + dtime, true);
xmlreq.onreadystatechange = function() {
	if (xmlreq.readyState != 4) return false;
	var isLoading = getElement('isLoading');
	if (isLoading && (xmlreq.status != 200)) {
		isLoading.innerHTML = ' - ERROR ' + xmlreq.status;
		return false;
	} else if (isLoading)
		isLoading.innerHTML = ' - REDRAWING...';
		
	// Clean up the map - don't strip out the weather layer
	removeMarkers(map, 'routeData');
	removeMarkers(map, 'routeWaypoints');
	removeMarkers(map, 'acPositions');
	removeMarkers(map, 'dcPositions');
	acPositions.length = 0;
	dcPositions.length = 0;
	displayObject(getElement('userSelect'), false);
	var cbo = document.forms[0].usrID;
	if (cbo) {
		selectedPilot = cbo.options[cbo.selectedIndex].text;
		cbo.options.length = 1;
	}

	// Parse the XML
	var xml = xmlreq.responseXML;
	if (!xml) return false;
	var xe = xml.documentElement;
	var ac = xe.getElementsByTagName("aircraft");
	gaEvent('ACARS', 'Aircraft Positions');
	for (var i = 0; i < ac.length; i++) {
		var a = ac[i]; var mrk = null;
		var p = new GLatLng(parseFloat(a.getAttribute("lat")), parseFloat(a.getAttribute("lng")));
		if (a.getAttribute("pal"))
			mrk = googleIconMarker(a.getAttribute("pal"), a.getAttribute("icon"), p, null);
		else if (a.getAttribute("color"))
			mrk = googleMarker(document.imgPath, a.getAttribute("color"), p, null);

		mrk.flight_id = a.getAttribute("flight_id");
		mrk.isBusy = (a.getAttribute("busy") == 'true');
		var tabs = parseInt(a.getAttribute("tabs"));
		GEvent.addListener(mrk, 'infowindowclose', function() { document.pauseRefresh = false; removeMarkers(map, 'routeData'); removeMarkers(map, 'routeWaypoints'); });
		if (tabs == 0) {
			var label = a.firstChild;
			mrk.infoLabel = label.data;
		} else {
			mrk.tabs = [];
			var tbs = a.getElementsByTagName("tab");
			for (var x = 0; x < tbs.length; x++) {
				var tab = tbs[x];
				var label = tab.firstChild;
				mrk.tabs.push(new GInfoWindowTab(tab.getAttribute("name"), label.data));
			}
		}

		// Add the user ID
		var pns = a.getElementsByTagName('pilot');
		if ((pns.length > 0) && (cbo != null)) {
			var pn = pns[0];
			var lbl = pn.firstChild.data;
			var id = pn.getAttribute('id');
			if (id != null)
				lbl = lbl + ' (' + id + ')';

			var o = new Option(lbl, id);
			o.mrk = mrk;
			try {
				cbo.add(o, null);
			} catch (err) {
				cbo.add(o); // IE hack
			}
			if (selectedPilot == id)
				cbo.selectedIndex = (cbo.options.length - 1);
		}

		// Set the the click handler
		GEvent.bind(mrk, 'click', mrk, clickAircraft);
		acPositions.push(mrk);
		map.addOverlay(mrk);
	} // for

	var dc = xe.getElementsByTagName("dispatch");
	if (dc.length > 0)
		gaEvent('ACARS', 'Dispatch Positions');
	for (var i = 0; i < dc.length; i++) {
		var d = dc[i]; var mrk = null;
		var p = new GLatLng(parseFloat(d.getAttribute("lat")), parseFloat(d.getAttribute("lng")));
		if (d.getAttribute("pal"))
			mrk = googleIconMarker(d.getAttribute("pal"), d.getAttribute("icon"), p, null);
		else if (d.getAttribute("color"))
			mrk = googleMarker(document.imgPath, d.getAttribute("color"), p, null);

		var tabs = parseInt(d.getAttribute("tabs"));
		mrk.range = parseInt(d.getAttribute("range"));
		mrk.isBusy = (d.getAttribute("busy") == 'true');
		GEvent.bind(mrk, 'infowindowclose', mrk, function() { document.pauseRefresh = false; if (this.rangeCircle) this.rangeCircle.hide(); });
		if (tabs == 0) {
			var le = d.getElementsByTagName("info");
			mrk.infoLabel = le[0].firstChild.data;
		} else {
			mrk.tabs = [];
			var tbs = d.getElementsByTagName("tab");
			for (var x = 0; x < tbs.length; x++) {
				var tab = tbs[x];
				var label = tab.firstChild;
				mrk.tabs.push(new GInfoWindowTab(tab.getAttribute("name"), label.data));
			}
		}

		// Add the user ID
		var pns = d.getElementsByTagName('pilot');
		if ((pns.length > 0) && (cbo != null)) {
			var pn = pns[0];
			var id = pn.getAttribute('id');
			var o = new Option(pn.firstChild.data + ' (' + id + '/Dispatcher)', id);
			o.mrk = mrk;
			try {
				cbo.add(o, null);
			} catch (err) {
				cbo.add(o); // IE hack
			}
			if (selectedPilot == id)
				cbo.selectedIndex = (cbo.options.length - 1);
		}

		// Set the the click handler
		GEvent.bind(mrk, 'click', mrk, clickDispatch);
		dcPositions.push(mrk);
		map.addOverlay(mrk);
	} // for

	// Enable the Google Earth button depending on if we have any aircraft
	enableElement('EarthButton', (ac.length > 0));

	// Display dispatch status
	var de = getElement('dispatchStatus');
	if ((de) && (dc.length > 0)) {
		de.className = 'ter bld caps';
		de.innerHTML = 'Dispatcher Currently Online';
	} else if (de) {
		de.className = 'bld caps';	
		de.innerHTML = 'Dispatcher Currently Offline';
	}

	// Focus on the map
	if (cbo)
		displayObject(getElement('userSelect'), (cbo.options.length > 1));
	if (isLoading)
		isLoading.innerHTML = ' - ' + (ac.length + dc.length) + ' CONNECTIONS';

	return true;
} // function

return xmlreq;
}

function clickAircraft()
{
// Check what info we display
var f = document.forms[0];
var isProgress = f.showProgress.checked;
var isRoute = f.showRoute.checked;
var isInfo = f.showInfo.checked;
gaEvent('ACARS', 'Flight Info', this.flight_id);

// Display the info
if (isInfo && (this.tabs))
	this.openInfoWindowTabsHtml(this.tabs)
else if (isInfo)
	this.openInfoWindowHtml(this.infoLabel);

// Display flight progress / route
if (isProgress || isRoute) {
	removeMarkers(map, 'routeData');
	removeMarkers(map, 'routeWaypoints');
	showFlightProgress(this, isProgress, isRoute);
}

document.pauseRefresh = true;
return true;
}

function clickDispatch()
{
// Check what info we display
var f = document.forms[0];
var isInfo = f.showInfo.checked;
gaEvent('ACARS', 'Dispatch Info');

//Display the info
if (isInfo && (this.tabs))
	this.openInfoWindowTabsHtml(this.tabs)
else if (isInfo)
	this.openInfoWindowHtml(this.infoLabel);

//Display flight progress / route
if (!this.rangeCircle) {
	this.rangeCircle = getServiceRange(this, this.range);
	if (this.rangeCircle) {
		gaEvent('ACARS', 'Dispatch Service Range');
		map.addOverlay(this.rangeCircle);
	}
} else
	this.rangeCircle.show();

document.pauseRefresh = true;
return true;
}

function showFlightProgress(marker, doProgress, doRoute)
{
// Build the XML Requester
var d = new Date();
var xreq = GXmlHttp.create();
xreq.open("GET", "acars_progress.ws?id=" + marker.flight_id + "&time=" + d.getTime() + "&route=" + doRoute, true);
xreq.onreadystatechange = function() {
	if ((xreq.readyState != 4) || (xreq.status != 200)) return false;

	// Load the XML
	var xdoc = xreq.responseXML;
	var wsdata = xdoc.documentElement;

	// Draw the flight route
	if (doRoute) {
		var wps = wsdata.getElementsByTagName("route");
		var waypoints = [];
		for (var i = 0; i < wps.length; i++) {
			var wp = wps[i];
			var p = new GLatLng(parseFloat(wp.getAttribute("lat")), parseFloat(wp.getAttribute("lng")));
			waypoints.push(p);
		} // for

		gaEvent('ACARS', 'Flight Route Info', marker.flight_id);
		routeWaypoints = new GPolyline(waypoints, '#AF8040', 2, 0.7, { geodesic:true });
		map.addOverlay(routeWaypoints);
	}

	// Draw the flight progress
	if (doProgress) {
		var pos = wsdata.getElementsByTagName("pos");
		var positions = [];
		for (var i = 0; i < pos.length; i++) {
			var pe = pos[i];
			var p = new GLatLng(parseFloat(pe.getAttribute("lat")), parseFloat(pe.getAttribute("lng")));
			positions.push(p);
		} // for

		// Draw the line
		gaEvent('ACARS', 'Flight Progress Info', marker.flight_id);
		routeData = new GPolyline(positions, '#4080AF', 2, 0.8);
		map.addOverlay(routeData);
	}

	return true;
} // function

xreq.send(null);
return true;
}

function getServiceRange(marker, range)
{
var pts = circle(marker.getLatLng(), range);
if (pts ==  null) return null;

// Set border/fill colors
var bColor = marker.isBusy ? '#c02020' : '#20c060';
var fColor = marker.isBusy ? '#802020' : '#208040';
return new GPolygon(pts, bColor, 1, 0.65, fColor, marker.isBusy ? 0.1 : 0.2); 
}

function zoomTo(combo)
{
var opt = combo.options[combo.selectedIndex];
if ((!opt) || (opt.mrk == null)) return false;

// Check if we zoom or just pan
var f = document.forms[0];
if (f.zoomToPilot.checked)
	map.setZoom(9);

// Pan to the marker
map.panTo(opt.mrk.getLatLng());
GEvent.trigger(opt.mrk, 'click');
return true;
}
