// the delay between updates (in milliseconds)
var delayMilliseconds = 5000;

// holds all of the tracks loaded from the database
var tracks = {};

// the google map object
var map = null;

// icons for departure and arrival locations
var icon_red = null;
var icon_blue = null;

// a list of icons for jets
var icon_jet = {};

// a list of icons for props
var icon_prop = {};

// the currently open info window id
var info_window_shown = null;

// called when the web page finishes loading
function loadACARS() {
	if (GBrowserIsCompatible()) {
		map = new GMap2(document.getElementById("map"));
		map.addControl(new GLargeMapControl());
		map.addControl(new GMapTypeControl());
		map.addMapType(G_PHYSICAL_MAP);
		map.setCenter(new GLatLng(0,0),2,G_PHYSICAL_MAP);
		buildIcons();
		updateTracks();
	}
}


// Requests the latest list of tracks from the database
function updateTracks() {
	var a = new Ajax('http://www.livedispatch.org/livedispatch/tracks.php?', {
		'method': 'get',
		'onComplete': onTrackUpdateCompleted,
		'onRequest': onTrackUpdateRequested,	
		'onFailed': onTrackUpdateFailed
	}).request();
}

// called when the request is made for the latest list of tracks
function onTrackUpdateRequested() {
	// show the busy icon
	$('busyicon').style.display='block';
}

// called when the request for the latest list of tracks fails
function onTrackUpdateFailed() {
	// hide the busy icon
	$('busyicon').style.display='none';
	// maybe show an error here somehow?
}

// called when the request for the latest list of tracks is completed
function onTrackUpdateCompleted(data) {
	// hide the busy icon
	$('busyicon').style.display='none';
	// load the data into a javascript object
	var objects = Json.evaluate(data);
	// iterate over the tracks, updating the display where necessary
	for(var id in objects) {
		var obj = objects[id];
		if($defined(tracks[id]))
			updateTrack(obj);
		else
			addTrack(obj);
		if(info_window_shown == id)
			map.updateInfoWindow(createInfoTabs(id));
	}
	// remove old tracks
	for(var id in tracks)
		if(!$defined(objects[id]))
			removeTrack(id);

	var has_tracks = false;
	for(var id in tracks) {
		has_tracks = true;
		break;
	}
	if(has_tracks)
		$('noflights_row').style.display = 'none';
	else
	    $('noflights_row').style.display = 'block';
	updateRowBackgrounds();
	
	setTimeout(updateTracks, delayMilliseconds);
}

// add a new track to the map
function addTrack(track) {
	// save some data
	tracks[track.id] = {};
	tracks[track.id].id = track.id;
	tracks[track.id].data = track;
	// the table row
	tracks[track.id].__row = $('flight_table').insertRow($('flight_table').rows.length);
	for(var i=0;i<track.tablerow.length;i++) {
		var cell = tracks[track.id].__row.insertCell(tracks[track.id].__row.cells.length);
		if(i==0 || i==10)
			cell.style.backgroundColor = '#ffffff';
		if(i==1) {
			cell.style.textAlign = 'left';
			cell.style.padding = '6px';
		}
		else
			cell.style.textAlign = 'center';
		cell.innerHTML = track.tablerow[i];
	}
	//tracks[track.id].__row.innerHTML = track.tablerow;
	// the aircraft marker
	createMarker(track.id,track);
	// start and end points
	tracks[track.id].__start_point = eval(track.arrival_loc);
	tracks[track.id].__end_point = eval(track.departure_loc);
	tracks[track.id].__start_marker = new GMarker(
		tracks[track.id].__start_point, icon_red);
	tracks[track.id].__end_marker = new GMarker(
		tracks[track.id].__end_point, icon_blue);
	// the routes
	createFlightPlan(track.id,track);
	createRoute(track.id,track);
	// flag to tell if the route detail is shown or not
	tracks[track.id].__route_shown = false;
	tracks[track.id].__toggle_route = false;
}

// update an existing track with new data
function updateTrack(track) {
	// update the table row
	for(var i=0;i<track.tablerow.length;i++)
		tracks[track.id].__row.cells[i].innerHTML = track.tablerow[i];
	
	// if the direction has changed, the marker needs a new icon,
	// but gmaps doesn't support icon changing on the fly, so the
	// marker has to be re-created
	if(tracks[track.id].data.direction != track.direction) {
		var update_info = (info_window_shown==track.id);
		removeMarker(track.id,track);
		createMarker(track.id,track);
		if(update_info)
			onIconDoubleClick(track.id);
	}
	else {
		tracks[track.id].__point = eval('new GLatLng('+track.position+')');
		tracks[track.id].__marker.setLatLng(tracks[track.id].__point);		
	}
		
	// update the route if it has changed
	if(tracks[track.id].data.route != track.route) {
		removeRoute(track.id,track);
		createRoute(track.id,track);
	}
	
	// update the flight plan if it has changed
	if(tracks[track.id].data.flight_plan != track.flight_plan) {
		removeFlightPlan(track.id,track);
		createFlightPlan(track.id,track);
	}
	
	// update the stored data
	tracks[track.id].data = track;
}

// remove a track from the map
function removeTrack(id) {
	map.removeOverlay(tracks[id].__marker);
	for(var i=2;i<$('flight_table').rows.length;i++) {
		if(tracks[id].__row == $('flight_table').rows[i]) {
			$('flight_table').deleteRow(i);
			break;
		}
	}
	delete tracks[id];
}

// build the initial collection of icons
function buildIcons() {
	icon_red = new GIcon();
	icon_red.image = "http://labs.google.com/ridefinder/images/mm_20_red.png";
	icon_red.shadow = "http://labs.google.com/ridefinder/images/mm_20_shadow.png";
	icon_red.iconSize = new GSize(12, 20);
	icon_red.shadowSize = new GSize(22, 20);
	icon_red.iconAnchor = new GPoint(6, 20);
	icon_red.infoWindowAnchor = new GPoint(5, 1);

	icon_blue = new GIcon();
	icon_blue.image = "http://labs.google.com/ridefinder/images/mm_20_blue.png";
	icon_blue.shadow = "http://labs.google.com/ridefinder/images/mm_20_shadow.png";
	icon_blue.iconSize = new GSize(12, 20);
	icon_blue.shadowSize = new GSize(22, 20);
	icon_blue.iconAnchor = new GPoint(6, 20);
	icon_blue.infoWindowAnchor = new GPoint(5, 1);

	// run through the directions and create an icon for a jet and a prop for each
	var directions = [
		'n','nne','ne','ene',
		'e','ese','se','sse',
		's','ssw','sw','wsw',
		'w','wnw','nw','nnw'];
	for(var i=0;i<directions.length;i++) {
		var d = directions[i];
		icon_prop[d] = new GIcon();
		icon_prop[d].image = "http://www.livedispatch.org/livedispatch/images/props/"+d+".png";
		icon_prop[d].iconSize = new GSize(32,32);
		icon_prop[d].shadowSize = new GSize(56,32);
		icon_prop[d].iconAnchor = new GPoint(16,16);
		icon_prop[d].infoWindowAnchor = new GPoint(16,0);
		icon_jet[d] = new GIcon();
		icon_jet[d].image = "http://www.livedispatch.org/livedispatch/images/"+d+".png";
		icon_jet[d].iconSize = new GSize(32,32);
		icon_jet[d].shadowSize = new GSize(56,32);
		icon_jet[d].iconAnchor = new GPoint(16,16);
		icon_jet[d].infoWindowAnchor = new GPoint(16,0);
	}
}

function getTrackIcon(track_data) {
	var d = track_data.direction.toLowerCase();
	if(track_data.is_prop)
		return icon_prop[d];
	else
		return icon_jet[d];
}

function createMarker(id,data) {
	tracks[id].__point = eval('new GLatLng('+data.position+')');
	tracks[id].__marker = new GMarker(tracks[id].__point, getTrackIcon(data));
	map.addOverlay(tracks[id].__marker);
	tracks[id].__mouseoverhandler = GEvent.addListener(
		tracks[id].__marker, 'mouseover', onIconMouseOver.pass([id]));
	tracks[id].__mouseouthandler = GEvent.addListener(
		tracks[id].__marker, 'mouseout', onIconMouseOut.pass([id]));
	tracks[id].__clickhandler = GEvent.addListener(
		tracks[id].__marker, 'click', onIconClick.pass([id]));
	tracks[id].__doubleclickhandler = GEvent.addListener(
		tracks[id].__marker, 'dblclick', onIconDoubleClick.pass([id]));
	tracks[id].__infoclosehandler = GEvent.addListener(
		tracks[id].__marker, 'infowindowclose', onIconInfoWindowClose.pass([id]));
}

function removeMarker(id,data) {
	map.removeOverlay(tracks[id].__marker);
	GEvent.removeListener(tracks[id].__mouseoverhandler);
	GEvent.removeListener(tracks[id].__mouseouthandler);
	GEvent.removeListener(tracks[id].__clickhandler);
	GEvent.removeListener(tracks[id].__doubleclickhandler);
	GEvent.removeListener(tracks[id].__infoclosehandler);
}

function createRoute(id,data) {
	tracks[id].__route = new GPolyline(
		eval('['+data.route+']'), "#FF0000", 2, 0.8);
	if(tracks[id].__routes_shown)
		map.addOverlay(tracks[id].__route);
}

function removeRoute(id,data) {
	if(tracks[id].__routes_shown)
		map.removeOverlay(tracks[id].__route);
}

function createFlightPlan(id,data) {
	tracks[id].__flight_plan = new GPolyline(
		eval('['+data.flight_plan+']'), "#5858ff", 2, 0.8);
	if(tracks[id].__routes_shown)
		map.addOverlay(tracks[id].__flight_plan);
}

function removeFlightPlan(id,data) {
	if(tracks[id].__routes_shown)
		map.removeOverlay(tracks[id].__flight_plan);
}

function updateRowBackgrounds() {
	var color1 = "#F3EFE5"; 
	var color2 = "#FFFFFF"; 
	for(var i=2;i<$('flight_table').rows.length;i++) {
		if(i%2)
			$('flight_table').rows[i].style.backgroundColor = color1;
		else
			$('flight_table').rows[i].style.backgroundColor = color2;
	}
}

function onIconMouseOver(id) {
	showRoutes(id);
}

function onIconClick(id) {
	toggleStickyRoutes(id);
}

function onIconDoubleClick(id) {
	info_window_shown = id;
	setStickyRoutes(id);
	tracks[id].__marker.openInfoWindowTabs(createInfoTabs(id));
}

function onIconMouseOut(id) {
	hideRoutes(id);
}

function onIconInfoWindowClose(id) {
	info_window_shown = null;
	unsetStickyRoutes(id);
}

function setStickyRoutes(id) {
	tracks[id].__toggle_route = true;
	showRoutes(id);
}

function unsetStickyRoutes(id) {
	tracks[id].__toggle_route = false;
	hideRoutes(id);
}

function toggleStickyRoutes(id) {
	if(tracks[id].__toggle_route)
		unsetStickyRoutes(id);
	else
		setStickyRoutes(id);
}

function showRoutes(id) {
	if(!tracks[id].__routes_shown) {
		tracks[id].__routes_shown = true;
		map.addOverlay(tracks[id].__flight_plan);
		map.addOverlay(tracks[id].__route);
		map.addOverlay(tracks[id].__start_marker);
		map.addOverlay(tracks[id].__end_marker);
	}
}

function hideRoutes(id) {
	if(tracks[id].__routes_shown && !tracks[id].__toggle_route) {
		tracks[id].__routes_shown = false;
		map.removeOverlay(tracks[id].__flight_plan);
		map.removeOverlay(tracks[id].__route);
		map.removeOverlay(tracks[id].__start_marker);
		map.removeOverlay(tracks[id].__end_marker);
	}
}

function createInfoTabs(id) {
	var tab_names = [
		"Pilot","Flight","Aircraft","Lights","Avionics"];
	var tabs = [];
	for(var i=0;i<tab_names.length;i++) {
		var div = document.createElement("DIV");
		div.style.width = "450px";
		div.innerHTML = tracks[id].data.tabs[i];
		tabs.push(new GInfoWindowTab(tab_names[i],div));
	}
	return tabs;
}

