var map, isIE = (/*@cc_on ! @*/ false),
cycle_delay = 2000,		// milliseconds
zoom_in_if_more_than = 20,
zoom_out_if_less_than = 6,
never_zoom_out_beyond_level = 4,
persistence_time = {
	"Weather": 1,		// days
	"Major Airports": 1,
	"Inbound": 30,
	"Outbound": 30,
	"Vicinity": 30
},
cache_planes = {}, cache_trails = {};

function notifyOpener() {
	if (self.opener || !self.opener.newwindow) self.opener.newwindow = self;
}

if (isIE)
	render_map(true);
else if (document.addEventListener)
	document.addEventListener("DOMContentLoaded", render_map, false);
else
	window.onload = render_map;

function render_map(ieDefer) {
	if (mapsize == "big") setInterval(notifyOpener, 200);
	OpenLayers.Util.onImageLoadErrorColor = "transparent";
	OpenLayers.Util.onImageLoadError = function() {
		this.src = "http://hub.flightaware.com/images/mapcontrol/blank.gif";
		this.style.display = "";
	};
	OpenLayers.Renderer.symbol.plane = [0,10, 1,8, 1,2, 9,-3, 1,-2, 1,-7, 3,-10, 0,-9, -3,-10, -1,-7, -1,-2, -9,-3, -1,2, -1,8, 0,10];

	var options = {
		theme: null,
		projection: new OpenLayers.Projection("EPSG:4326"),
		maxResolution: 0.6,
		buffer: 0,
		maxExtent: new OpenLayers.Bounds(-180, -90, 180, 90),
		restrictedExtent: new OpenLayers.Bounds(-180, -90, 180, 90),
		controls: [
			new OpenLayers.Control.Navigation(),
			new OpenLayers.Control.KeyboardDefaults(),
			new OpenLayers.Control.Attribution(),
			new OpenLayers.Control.PanPanel(),
			new OpenLayers.Control.ZoomPanel(),
			new OpenLayers.Control.LayerSwitcher(),
			new OpenLayers.Control.CookieSetter(),
			new OpenLayers.Control.ScaleLine()
		]
	};
	map = new OpenLayers.Map("map", options);

// *** Dummy layer ***
	dummy = new OpenLayers.Layer(
		"Dummy", {
			isBaseLayer: true,
			displayInLayerSwitcher: false,
			attribution: "<div>&copy; 2009 FlightAware.com</div>",
			numZoomLevels: 11
		}
	);
	map.addLayer(dummy);

// *** Terrain layer from TileCache ***
	classic = new OpenLayers.Layer.TileCache(
		"Classic",
		"http://" + tile_cdn + "/images/tilecache/",
		"all", {
			isBaseLayer: false,
			visibility: false,
			displayInLayerSwitcher: false,
			gutter: 0,
			buffer: 0,
			tileSize: new OpenLayers.Size(600, 600)
		}
	);
	map.addLayer(classic);

// *** True Marble from TileCache ***
    earthview = new OpenLayers.Layer.TileCache(
		"Earth View",
		"http://" + tile_cdn + "/images/tilecache/",
		"marble", {
			isBaseLayer: false,
			visibility: false,
			displayInLayerSwitcher: false,
			format: "image/jpeg",
			gutter: 0,
			buffer: 0,
			tileSize: new OpenLayers.Size(600, 600),
			attribution: "<span>Imagery &copy; Unearthed Outdoors</span>"
        }
	);
	map.addLayer(earthview);

// *** Sectionals from TileCache ***
    aviationsectional = new OpenLayers.Layer.TileCache(
		"Aviation Sectional",
		"http://" + tile_cdn + "/images/tilecache/",
		"usasectional", {
			isBaseLayer: false,
			visibility: false,
			displayInLayerSwitcher: false,
			format: "image/jpeg",
            gutter: 0,
            buffer: 0,
            tileSize: new OpenLayers.Size(600, 600),
			maxExtent: new OpenLayers.Bounds(-169, 18, -60, 72)
        }
	);
	map.addLayer(aviationsectional);

// *** Radar weather layer from FlexMaps ***
	weather = new OpenLayers.Layer.WMS("Weather",
		"http://" + weather_cdn + "/ajax/weather.rvt", {
			cdnEnabled: cdnEnabled,
			clock: nexrad_time
		}, {
			DEFAULT_PARAMS: { },
			isBaseLayer: false,
			getURL: FlexGetURL,
			gutter: 0,
			buffer: 0,
			opacity: 0.30,
			tileSize: new OpenLayers.Size(1000, 1000),
			maxExtent: new OpenLayers.Bounds(-126, 24, -66, 50),
			attribution: "<span>Weather: " + zulu_date(nexrad_time * 1000) + "</span>"
        }
	);
	map.addLayer(weather);

	draw_controls(document.getElementById("map"));

// *** Airport styles  ***
	airport_Classic = new OpenLayers.Style({
		label: "  ${label}  ",
		fillColor: "#00FF00",
		fontColor: "#00FF00",
		fontSize: "13px",
		fontFamily: "Lucida Sans, Arial, Helvetica",
		pointRadius: 2,
		labelAlign: "lm"
	});
	airport_EarthView = new OpenLayers.Style({
		fillColor: "#ED8000",
		fontColor: "#ED8000"
	});
	airport_AviationSectional = new OpenLayers.Style({
		fillColor: "#0000CC",
		fontColor: "#0000CC",
		pointRadius: 3
	});
	airport_stylemap = new OpenLayers.StyleMap({
		"default": airport_Classic,
		EarthView: airport_EarthView,
		AviationSectional: airport_AviationSectional
	});

// *** Major airport styles  ***
	major_Classic = new OpenLayers.Style({
			label: "  ${getLabel}  ",
			labelAlign: "lm",
			fontSize: "12px",
			fontFamily: "Lucida Sans, Arial, Helvetica",
			fillColor: "#FFFF00",
			fontColor: "#FFFF00",
			pointRadius: 2
		}, { context: { getLabel: function(feature) { if (feature.layer.map.getZoom() > 3) return feature.attributes.label; else return ""; } }
	});
	major_EarthView = new OpenLayers.Style({
		fillColor: "#ED8000",
		fontColor: "#ED8000"
	});
	major_AviationSectional = new OpenLayers.Style({
		fillColor: "#0000CC",
		fontColor: "#0000CC",
		pointRadius: 3
	});
	major_hover = new OpenLayers.Style({
		fillColor: "#0000FF",
		pointRadius: 5
	});
	major_stylemap = new OpenLayers.StyleMap({
		"default": major_Classic,
		EarthView: major_EarthView,
		AviationSectional: major_AviationSectional,
		highlight: major_hover
	});

// *** Datablock style ***
	plane_hover = new OpenLayers.Style({
		fillColor: "#FFFFFF",
		strokeColor: "#FFFFFF",
		label: " \n${getLabel}\n ",
		labelAlign: "lt"
		}, {
			context: {
				getLabel: function(feature) {
					if (feature.geometry.CLASS_NAME == "OpenLayers.Geometry.Point")
						return feature.attributes.ident + " " + feature.attributes.type + "\n" + feature.attributes.altitude + " " + feature.attributes.groundspeed + "\n" + feature.attributes.origin + " " + feature.attributes.destination;
					else
						return "";
				}
			}
		}
	);

// *** Route style ***
	route_Classic = new OpenLayers.Style({
		strokeWidth: 1,
		strokeDashstyle: "longdash",
		strokeColor: "#4499FF",
		stroke: true
	});
	route_EarthView = new OpenLayers.Style({
		strokeWidth: 1,
		strokeDashstyle: "longdash",
		strokeOpacity: 0.7,
		strokeColor: "#4499FF"
	});
	route_AviationSectional = new OpenLayers.Style({
		strokeWidth: 2,
		strokeDashstyle: "dash",
		strokeOpacity: 0.4,
		fillColor: "#0000CC",
		strokeColor: "#0000CC"
	});
	route_stylemap = new OpenLayers.StyleMap({
		"default": route_Classic,
		EarthView: route_EarthView,
		AviationSectional: route_AviationSectional
	});

// *** Inbound styles  ***
	inbound_Classic = new OpenLayers.Style({
		fontColor: "#00FFFF",
		fontSize: "11px",
		fontFamily: "Lucida Sans, Arial, Helvetica",
		strokeColor: "#00FFFF",
		fillColor: "#00FFFF",
		stroke: true,
		graphicName: "plane",
		rotation: "${direction}",
		pointRadius: 5
	});
	inbound_EarthView = new OpenLayers.Style({
	});
	inbound_AviationSectional = new OpenLayers.Style({
		fontColor: "#770000",
		strokeColor: "#770000",
		fillColor: "#770000"
	});
	inbound_stylemap = new OpenLayers.StyleMap({
		"default": inbound_Classic,
		EarthView: inbound_EarthView,
		AviationSectional: inbound_AviationSectional,
		highlight: plane_hover
	});

// *** Outbound styles  ***
	outbound_Classic = new OpenLayers.Style({
		fontColor: "#00FFFF",
		fontSize: "11px",
		fontFamily: "Lucida Sans, Arial, Helvetica",
		strokeColor: "#00FFFF",
		fillColor: "#00FFFF",
		stroke: true,
		graphicName: "plane",
		rotation: "${direction}",
		pointRadius: 5
	});
	outbound_EarthView = new OpenLayers.Style({
	});
	outbound_AviationSectional = new OpenLayers.Style({
		fontColor: "#770000",
		strokeColor: "#770000",
		fillColor: "#770000"
	});
	outbound_stylemap = new OpenLayers.StyleMap({
		"default": outbound_Classic,
		EarthView: outbound_EarthView,
		AviationSectional: outbound_AviationSectional,
		highlight: plane_hover
	});

// *** Vicinity styles  ***
	vicinity_Classic = new OpenLayers.Style({
		fontColor: "#00FF00",
		fontSize: "11px",
		fontFamily: "Lucida Sans, Arial, Helvetica",
		strokeColor: "#00FF00",
		fillColor: "#00FF00",
		stroke: true,
		graphicName: "plane",
		rotation: "${direction}",
		pointRadius: 5
	});
	vicinity_EarthView = new OpenLayers.Style({
	});
	vicinity_AviationSectional = new OpenLayers.Style({
		fontColor: "#000000",
		strokeColor: "#000000",
		fillColor: "#000000"
	});
	vicinity_stylemap = new OpenLayers.StyleMap({
		"default": vicinity_Classic,
		EarthView: vicinity_EarthView,
		AviationSectional: vicinity_AviationSectional,
		highlight: plane_hover
	});

// *** Other styles ***
	text_shadow_style = new OpenLayers.Style({
		fontColor: "#000000",
		pointRadius: 0
	});
	white_shadow = new OpenLayers.Style({
		fontColor: "#FFFFFF",
		pointRadius: 0
	});
	plane_shadow_style = new OpenLayers.Style({
		fillColor: "#000000",
		label: ""
	});

	read_airport = new OpenLayers.Format.GeoJSON();
	read_major = new OpenLayers.Format.GeoJSON();
	read_inbound = new OpenLayers.Format.GeoJSON();
	read_outbound = new OpenLayers.Format.GeoJSON();
	read_route = new OpenLayers.Format.GeoJSON();

	airport_parsed = read_airport.read(json_airport);
	major_parsed = read_major.read(major_airports);
	inbound_parsed = read_inbound.read(json_inbound);
	outbound_parsed = read_outbound.read(json_outbound);
	route_parsed = read_route.read(json_routes);

	cookiearray = get_cookies();
	if (cookiearray["BaseLayer"] && typeof window[cookiearray["BaseLayer"].toLowerCase()] !== "undefined") {
		window[cookiearray["BaseLayer"].toLowerCase()].setVisibility(true);
		lastActive = document.getElementById(cookiearray["BaseLayer"]);
		lastActive.className = "Active";
	} else {
		classic.setVisibility(true);
		lastActive = document.getElementById("Classic");
		lastActive.className = "Active";
	}

	set_center();

	if (ieDefer === true)
		window.attachEvent("onload", render_vectors);
	else
		render_vectors();
}

function set_center(autofit) {
	if (cookiearray["center"] && cookiearray["airport_id"] && cookiearray["airport_id"] == airport_id) {
		var vals = cookiearray["center"].split(",");
		map.setCenter(new OpenLayers.LonLat(vals[0].split(":")[1], vals[1].split(":")[1]), cookiearray["zoom"] * 1);
	} else {
		if (autofit === true) {
			var planes_in_view = count_planes_in_layers([inbound, outbound]);
			if (planes_in_view < zoom_out_if_less_than) {
				auto_zoom(-1);
			} else if (planes_in_view > zoom_in_if_more_than) {
				auto_zoom(1);
			}
		} else {
			map.setCenter(new OpenLayers.LonLat(mapCenter[1], mapCenter[0]), 8);
		}
	}
}

function auto_zoom(step) {
	map.setCenter(map.getCenter(), map.getZoom() + step);
}

function reClosure() {
	return map.restrictedExtent.toArray().join(",");
}

function render_vectors() {
	if (mapsize == "regular" && typeof newwindow !== "undefined" && newwindow.location && !newwindow.closed) popitup("/live/" + imgWindow, imgWidth, imgHeight);

// *** Airport with label ***
	airportLayer = new OpenLayers.Layer.Vector("Airport", {displayInLayerSwitcher: false, styleMap: airport_stylemap, displayError: notsupported});
	airportLayer.addFeatures(airport_parsed);
	map.addLayer(airportLayer);

// *** Major airports ***
	major = new OpenLayers.Layer.Vector("Major Airports", {styleMap: major_stylemap});
	major.addFeatures(major_parsed);
	map.addLayer(major);
	remove_dupe_airports(major.features, airport_id);

// *** Routes layer ***
	route = new OpenLayers.Layer.Vector("Hover for Route", {styleMap: route_stylemap});
	build_route_cache(route_parsed);
	map.addLayer(route);

// *** Inbound and Outbound flight layers ***
	inbound = new OpenLayers.Layer.Vector("Inbound", {styleMap: inbound_stylemap});
	inbound.addFeatures(inbound_parsed);
	map.addLayer(inbound);

	outbound = new OpenLayers.Layer.Vector("Outbound", {styleMap: outbound_stylemap});
	outbound.addFeatures(outbound_parsed);
	map.addLayer(outbound);

	set_pan_bounds();

	vicinity = new OpenLayers.Layer.Vector("Vicinity", {
		strategies: [new OpenLayers.Strategy.Fixed()],
		protocol: new OpenLayers.Protocol.HTTP({
			url: "/ajax/airport_vicinity_json.rvt",
			params: { key: api_key, time: api_time, exclude: airport_id, bbox: reClosure() },
			format: new OpenLayers.Format.GeoJSON()
		}),
		styleMap: vicinity_stylemap
	});
	map.addLayer(vicinity);

	var overlays = {weather: "Weather", major: "Major Airports", route: "Hover for Route", inbound: "Inbound", outbound: "Outbound", vicinity: "Vicinity"};  // need to turn off weather earlier
	for (var x in overlays) {
		if (cookiearray[overlays[x].replace(" ", "")]) {
			window[x].setVisibility(cookiearray[overlays[x].replace(" ", "")] * 1);
		}
	}

	bind_map_hovers();

// *** Control panels, persistence, and autofit ***
	if (cookiearray["BaseLayer"] && typeof window[cookiearray["BaseLayer"].toLowerCase()] !== "undefined") {
		switchVectorStyles(cookiearray["BaseLayer"]);
	} else {
		switchVectorStyles("Classic");
	}

	map.events.on({"zoomend": function (e) {
		set_pan_bounds();
		vicinity.protocol.params.bbox = reClosure();
		vicinity.refresh();
		build_cycle_list();
	}});
	map.events.on({"moveend": function (e) {
		build_cycle_list();
	}});
	map.events.on({"changelayer": function (e) {
		if (e.layer.CLASS_NAME == "OpenLayers.Layer.TileCache") {
			switchVectorStyles(e.layer.name.replace(" ",""));
		} else {
			if (e.layer == vicinity) {
				vicinity.protocol.params.bbox = reClosure();
				vicinity.refresh();
			}
			set_cookie(e.layer.name.replace(" ", ""), e.layer.getVisibility() * 1, 24 * persistence_time[e.layer.name]);
			build_cycle_list();
		}
	}});
	vicinity.events.on({"loadend": function (e) {
		cache_plane_features([vicinity]);
		switchVectorStyles(baseLayerName);
	}});

//	moveSVGlabels(planes.features);
	setTimeout("classic.addOptions({transitionEffect: 'resize'}); aviationsectional.addOptions({transitionEffect: 'resize'}); earthview.addOptions({transitionEffect: 'resize'}); weather.addOptions({transitionEffect: 'resize'});", 2000);

	//bind_events_to_rowids();
	cache_plane_features([inbound, outbound]);
	attach_row_hovers();
	build_cycle_list();
	cycle = setTimeout("cycle_datablocks();", cycle_delay);
}

function bind_map_hovers() {
	highlightCtrl = new OpenLayers.Control.SelectFeature([inbound, outbound, vicinity, major], {
		hover: true,
		highlightOnly: true,
		renderIntent: "highlight",
		eventListeners: {
			beforefeaturehighlighted: dim_all_highlighted,
			featurehighlighted: highlight_row,
			featureunhighlighted: dim_row
		}
	});
	map.addControl(highlightCtrl);
	highlightCtrl.activate();

	clickCtrl = new OpenLayers.Control.SelectFeature([inbound, outbound, vicinity, major],
		{onSelect: go_to_flight},
		{clickout: true}
	);
	map.addControl(clickCtrl);
	clickCtrl.activate();
}

function set_pan_bounds() {
	var lastLoc = airportLayer.features[0].geometry,
		xOffset = map.getResolution() * document.getElementById("map").offsetWidth,
		yOffset = map.getResolution() * document.getElementById("map").offsetHeight;
	map.restrictedExtent = new OpenLayers.Bounds(
		lastLoc.x - xOffset,
		lastLoc.y - yOffset,
		lastLoc.x + xOffset,
		lastLoc.y + yOffset
	);
}

function remove_dupe_airports(farray, airport) {
	for (var x = farray.length - 1; x >= 0; x--) {
		if (farray[x].attributes.label == airport) {
			major.removeFeatures(farray[x]);
		}
	}
}

function in_array(str, arr) {
	for (var x in arr) {
		if (arr[x] === str) return true;
	}
	return false;
}

function build_cycle_list() {
	var extent = map.getExtent(), all_layers = [inbound, outbound], layers = [];
	cycle_list = [], current_block = -1;

	for (var x in all_layers) {
		if (all_layers[x].visibility) {
			var layer_name = all_layers[x].name.toLowerCase() + "_tailsequence";
			if (typeof window[layer_name] !== "undefined") {
				var tail_list = window[layer_name];
				for (var y = 0; y < tail_list.length; y++) {
					if (tail_list[y] in cache_planes && extent.intersectsBounds(cache_planes[tail_list[y]].geometry.getBounds())) {
						cycle_list.push(tail_list[y]);
					}
				}
			}
			layers.push(all_layers[x]);
		}
	}

	dim_all_highlighted();
	for (var x in layers) {
		for (var y = 0; y < layers[x].features.length; y++) {
			if (layers[x].features[y].geometry.CLASS_NAME === "OpenLayers.Geometry.Point" && extent.intersectsBounds(layers[x].features[y].geometry.getBounds()) && !in_array(layers[x].features[y].attributes.ident, cycle_list)) {
				cycle_list.push(layers[x].features[y].attributes.ident);
			}
		}
	}
}

function count_planes_in_layers(layers) {
	var count = 0, extent = map.getExtent();
	for (var x in layers) {
		for (var y = 0; y < layers[x].features.length; y++) {
			if (layers[x].features[y].geometry.CLASS_NAME === "OpenLayers.Geometry.Point" && extent.intersectsBounds(layers[x].features[y].geometry.getBounds())) {
				count++;
			}
		}
	}
	return count;
}

function cycle_datablocks() {
	var temp_plane = cache_planes[cycle_list[current_block % cycle_list.length]];
	if (current_block !== -1 && cycle_list.length && temp_plane.bounds !== null) highlightCtrl.unhighlight(temp_plane);
	current_block++;
	if (cycle_list.length && current_block >= 0) highlightCtrl.highlight(cache_planes[cycle_list[current_block % cycle_list.length]]);
	cycle = setTimeout("cycle_datablocks();", cycle_delay);
}

function cache_plane_features(layers) {
	for (var x in layers) {
		for (var y in layers[x].features) {
			if (layers[x].features[y].geometry.CLASS_NAME == "OpenLayers.Geometry.Point")
				cache_planes[layers[x].features[y].attributes.ident] = layers[x].features[y];
			else if (layers[x].features[y].geometry.CLASS_NAME == "OpenLayers.Geometry.LineString")
				cache_trails[layers[x].features[y].attributes.ident] = layers[x].features[y];
		}
	}
}

function attach_row_hovers() {
	var alltrs = document.getElementsByTagName("tr");
	for (var x = 0; x < alltrs.length; x++) {
		if (alltrs[x].id.indexOf("Row_") !== -1) {
			alltrs[x].onmouseover = highlight_plane;
			alltrs[x].onmouseout = dim_plane;
		}
	}
}

function highlight_plane(e) {
	var ident = this.id.replace(/Row_\w+_(.+)$/, "$1"), lay = this.id.replace(/^.*_(.+)_.*$/, "$1");
	if (ident in cache_planes) highlightCtrl.highlight(cache_planes[ident]);
}

function dim_plane(e) {
	var ident = this.id.replace(/Row_\w+_(.+)$/, "$1"), lay = this.id.replace(/^.*_(.+)_.*$/, "$1");
	if (ident in cache_planes) highlightCtrl.unhighlight(cache_planes[ident]);
}

function highlight_row(e) {
	clearTimeout(cycle);

	var ident = e.feature.attributes.ident, type = e.feature.geometry.CLASS_NAME, lay = e.feature.layer.name.toLowerCase(), rowid = "Row_" + lay + "_" + ident, extent = map.getExtent();
	if (document.getElementById(rowid) && extent.intersectsBounds(e.feature.geometry.getBounds()))
		document.getElementById(rowid).style.backgroundColor = "#f3ed86";
	switch_render_intent(e.feature.layer, type, ident, "highlight");
}
function dim_row(e) {
	var ident = e.feature.attributes.ident, type = e.feature.geometry.CLASS_NAME, lay = e.feature.layer.name.toLowerCase(), rowid = "Row_" + lay + "_" + ident, extent = map.getExtent();
	if (document.getElementById(rowid) && extent.intersectsBounds(e.feature.geometry.getBounds()))
		document.getElementById(rowid).style.backgroundColor = "";
	switch_render_intent(e.feature.layer, type, ident, baseLayerName);

	clearTimeout(cycle);
	cycle = setTimeout("cycle_datablocks();", cycle_delay);
}

function dim_all_highlighted() {
	var layers = [inbound, outbound];
	for (var x in layers) {
		for (var y = 0; y < layers[x].features.length; y++) {
			if (layers[x].features[y].renderIntent == "highlight") {
				highlightCtrl.unhighlight(layers[x].features[y]);
			}
		}
	}
}

function switch_render_intent(layer, type, ident, intent) {
	if (type == "OpenLayers.Geometry.LineString") {
		if (ident in cache_planes) {
			cache_planes[ident].renderIntent = intent;
			layer.drawFeature(cache_planes[ident]);
		}
	} else if (type == "OpenLayers.Geometry.Point") {
		if (ident in cache_trails) {
			cache_trails[ident].renderIntent = intent;
			layer.drawFeature(cache_trails[ident]);
		}
	}
	if (ident in cache_route) {
		if (intent == "highlight")
			route.addFeatures([cache_route[ident]]);
		else
			route.removeFeatures([cache_route[ident]]);
	}
}

function go_to_flight(e) {
	var attrib = {"flight": "ident", "airport": "label"};
	if (e.attributes.ident)
		var type = "flight";
	else if (e.attributes.label)
		var type = "airport";

	if (mapsize === "big") {
		if (type === "airport") location.href = "/live/airport_status_bigmap.rvt?airport=" + e.attributes[attrib[type]];
		if (self.opener) self.opener.location.href = "/live/" + type + "/" + e.attributes[attrib[type]];
	} else {
		location.href = "/live/" + type + "/" + e.attributes[attrib[type]];
	}
}

function switchVectorStyles(base) {
	baseLayerName = base;
	layers = [airportLayer, route, major, inbound, outbound, vicinity];

	for (var layer in layers) {
		for (var x = 0; x < layers[layer].features.length; x++)
			layers[layer].features[x].renderIntent = base;
		layers[layer].redraw();
	}
}

function notsupported() {
	var oldMapImage = new Image();
	oldMapImage.src = oldMapUrl;
	if (mapsize === "regular") {
		oldMapImage.onclick = function () { popitup("/live/" + imgWindow, imgWidth, imgHeight); };
		oldMapImage.style.cursor = "pointer";
	}
	map.destroy();
	document.getElementById("map").innerHTML = "";
	document.getElementById("map").appendChild(oldMapImage);
}

function update_plane_shadows(layer, fullupdate, view) {
	var text_shadow = 0, plane_shadow = 1, green_plane = 2;

	if (layer.features.length) {
		if (!fullupdate) {
			var lastLoc = layer.features[green_plane].geometry,
			scaleAltitude = Math.min(5, layer.features[green_plane].attributes.altitude / 60), newloc;
		}

		if (fullupdate) {
			if (view === "AviationSectional")
				layer.features[text_shadow].renderIntent = "white_shadow";
			else
				layer.features[text_shadow].renderIntent = "text_shadow";
		} else {
			newloc = new OpenLayers.LonLat(lastLoc.x + map.getResolution(), lastLoc.y - map.getResolution());
			layer.features[text_shadow].move(newloc);
			layer.features[text_shadow].move(newloc); // fix unknown bug
		}

		if (fullupdate) {
			layer.features[plane_shadow].renderIntent = "plane_shadow";
		} else {
			newloc = new OpenLayers.LonLat(lastLoc.x + map.getResolution() * scaleAltitude, lastLoc.y - map.getResolution() * scaleAltitude);
			layer.features[plane_shadow].move(newloc);
			layer.features[plane_shadow].move(newloc); // fix unknown bug

			newloc = new OpenLayers.LonLat(lastLoc.x, lastLoc.y); // another unknown bug relating to zIndex
			layer.features[green_plane].move(newloc);
			layer.features[green_plane].move(newloc);
		}
	}
	layer.redraw();
}

function reposition_multiline_label() {
}

function moveSVGlabels(farray) {
	update_plane_shadows(planes, false, "");

	// Multi-line vector labels
	for (var x = farray.length - 1; x >= 0; x--) {
		var tspans = document.getElementsByTagName("tspan");
		for (var y = 0; y < tspans.length; y++) {
			if (tspans[y].id.indexOf("MultiLine_") !== -1) {
				tspans[y].setAttributeNS(null, "x", tspans[y].parentNode.getAttributeNS(null, "x"));
				if (tspans[y].parentNode.getAttributeNS(null, "dominant-baseline") == "start") {
//					alert(document.defaultView.getComputedStyle(tspans[y], null).getPropertyValue("width"));
//					tspans[y].setAttributeNS(null, "x", tspans[y].parentNode.getAttributeNS(null, "x") - tspans[y].getAttributeNS(null, "width"));
				}
			}
		}
	}
	planes.redraw();
}

function splitTracks(farray) {
	for (var x = farray.length - 1; x >= 0; x--) {
		switch (farray[x].geometry.CLASS_NAME) {
			case "OpenLayers.Geometry.Point":
				if (farray[x].attributes.label) {
					// Origin or destination
					farray[x].attributes.hAlign = headingAlign(farray[0].attributes.direction, farray[x].attributes.type == "origin");
					window[farray[x].attributes.type] = farray[x].attributes.label;
					tracks.addFeatures(farray[x].clone());
					vectors.removeFeatures(farray[x]);
				} else {
					farray[x].attributes.hAlign = headingAlign(farray[x].attributes.direction);
					planes.addFeatures(farray[x].clone()); // text shadow
					planes.addFeatures(farray[x].clone()); // plane shadow
					planes.addFeatures(farray[x].clone()); // green plane
					vectors.removeFeatures(farray[x]);
				}
				break;
			case "OpenLayers.Geometry.LineString":
				tracks.addFeatures(farray[x].clone());
				vectors.removeFeatures(farray[x]);
				break;
		}
	}
	tracks.redraw();
	planes.redraw();
	major.redraw();
}

function headingAlign(degrees, reverse) {
	if (reverse === true)
		degrees = (degrees + 180) % 360;
	if (degrees < 90)
		return "bl";
	else if (degrees < 180)
		return "br";
	else if (degrees < 270)
		return "tr";
	else
		return "tl";
}

function get_cookies() {
	var cookiearray = document.cookie.split("; "), resultcookie = [], x, piece;
	for (x in cookiearray) {
		piece = cookiearray[x].split("=");
		resultcookie[piece[0]] = piece[1];
	}
	return (resultcookie);
}

function set_cookie(name, value, hours) {
	document.cookie = name + "=" + value + "; expires=" + (value !== "" ? (new Date((new Date()).getTime() + 1000*60*60*hours)).toGMTString() : new Date(1997, 10, 1).toGMTString()) + "; path=/";
}

function FlexGetURL(bounds) {
	bounds = this.adjustBounds(bounds);
	var imageSize = this.getImageSize();
	var url = this.getFullRequestString({
		time:		this.params.nexrad,
		lowlat:		bounds.bottom,
		lowlon:		bounds.left,
		hilat:		bounds.top,
		hilon:		bounds.right,
		height:		imageSize.h,
		width:		imageSize.w
	});
	return url;
}

function popitup(url, width, height) {
	if (typeof newwindow !== "undefined" && newwindow.location && !newwindow.closed) {
		newwindow.location.href = url;
		newwindow.focus();
	} else {
		newwindow = window.open(url,'FlightAwareBigMap','width=' + width +',height=' + height + ',menubar=no,resizeable=yes,resizable=yes,scrollbars=no,toolbar=no,location=no,status=no,titlebar=no');
	}
}

function draw_controls(container) {
	var big_window_icon = new Image();
	big_window_icon.src = "http://hub.flightaware.com/images/mapcontrol/fa-open-fullscreen.png";
	big_window_icon.className = "FullscreenIcon";
	big_window_icon.onclick = function () { popitup("/live/" + imgWindow, imgWidth, imgHeight); };
	if (mapsize === "regular") container.appendChild(big_window_icon);

	var baselayers = document.createElement("div"), buttons = [];
	baselayers.className = "BaseLayerHolder";
	for (var lay = map.layers.length - 1; lay >= 0; lay--) if (map.layers[lay].CLASS_NAME == "OpenLayers.Layer.TileCache") {
		buttons[lay] = document.createElement("div");
		buttons[lay].innerHTML = map.layers[lay].name;
		buttons[lay].idx = lay;
		buttons[lay].id = map.layers[lay].name.replace(" ", "");
		buttons[lay].onclick = switchBaseLayer;
		baselayers.appendChild(buttons[lay]);
	}
	container.appendChild(baselayers);
}

function switchBaseLayer(e) {
	if (typeof lastActive !== "undefined") lastActive.className = "";
	set_cookie("BaseLayer", map.layers[this.idx].name.replace(" ",""), 24);
	for (var lay = map.layers.length - 1; lay >= 0; lay--) {
		if (map.layers[lay].CLASS_NAME == "OpenLayers.Layer.TileCache") {
			map.layers[lay].setVisibility(this.idx == lay);
		}
	}
	switchVectorStyles(this.id);
	this.className = this.className + "Active";
	lastActive = this;
}

function build_route_cache(features) {
	cache_route = {};
	for (var x = 0; x < features.length; x++) {
		cache_route[features[x].attributes.ident] = features[x];
	}
}

function zulu_date(timestring) {
	var t = new Date(timestring),
	months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];

	return t.getDate() + " " + months[t.getUTCMonth()] + " " + String(t.getUTCFullYear()).slice(-2) + " " + ("00" + t.getUTCHours()).slice(-2) + ":" + ("00" + t.getUTCMinutes()).slice(-2) + "Z";
}
