// Global variables
var map;
var xml;
var center;
var zoom;
var lang = (language == 'en' ? 'english' : 'french');

// Initialize
// Use this instead of $(document).ready() to prevent a WebKit bug
// where the panel is sized incorrectly.
// http://36flavours.com/2010/01/jquery-document-ready-bug-in-safari-webkit/
$(window).load(function() {
	loadMap();
});


/*
 * Loads the Google Map.
 */
function loadMap() {
	if (google.maps.BrowserIsCompatible()) 	{
		// DOM Events
		var switcher = document.getElementById('metro_lines');
		google.maps.Event.addDomListener(switcher, 'change', switchLine);
		google.maps.Event.addDomListener(window, 'resize', resizeList);
		google.maps.Event.addDomListener(window, 'unload', google.maps.Unload);
		
		// Create map
		var mapOptions = {
			googleBarOptions: {
				suppressInitialResultSelection: true,
				suppressZoomToBounds: true
			}
		}
		map = new google.maps.Map2(document.getElementById('map'), mapOptions);
		map.addControl(new google.maps.LargeMapControl3D()); // Zoom/Pan
		map.addControl(new google.maps.MapTypeControl()); // Map, Satellite, Hybrid
		map.addControl(new google.maps.OverviewMapControl()); // Overview square
		map.enableGoogleBar(); // Local search
		//map.enableScrollWheelZoom(); // Zoom with scroll wheel
		
		center = new google.maps.LatLng(45.522134781505805, -73.57792854309082);
		zoom = 12;
		map.setCenter(center, zoom);
		
		// Download/parse XML, add markers, lines, stations to panel, resize list
		google.maps.DownloadUrl('/xml/metro.xml', function(data, responseCode) {
			xml = google.maps.Xml.parse(data);
			addOverlays();
			addLines();
			addStations();
			resizeList();
		});
	}
	else {
		var html = '<div id="error">';
		html += '<p><img src="/images/logo.png" alt="" /></p>';
		html += '<h1>'+notCompatible+'</h1>';
		html += '</div>';
		$('body').empty().html(html);
	}
}


/*
 * Adds the overlays for the metro lines and stations.
 * Includes both markers and polylines.
 *
 * @param		selected_line (string) The selected metro line.
 */
function addOverlays(selected_line) {
	// Clear map overlays; re-center map and reset zoom
	map.clearOverlays();
	map.panTo(center);
	map.setZoom(zoom);
	// Metro lines
	var lines = xml.getElementsByTagName('line');
	for (var x = 0; x < lines.length; x++) {
		// Get line info
		var line = getLineInfo(lines[x].getAttribute('id'));
		// Add to metro line picklist
		if (selected_line == line.id || selected_line == 'all' || !selected_line) {
			// Metro stops
			var stops = lines[x].getElementsByTagName('stop');
			for (var y = 0; y < stops.length; y++) {
				// Get station info
				var station = getStationInfo(stops[y].getAttribute('id'));
				// Create marker
				addMarker(station);
				// Create polyline
				if (y+1 < stops.length) {
					var next_station = getStationInfo(stops[y+1].getAttribute('id'));
					addPolyline(
						station.latitude,
						station.longitude,
						next_station.latitude,
						next_station.longitude,
						line.color
					);
				}
			}
		}
	}
}


/*
 * Adds the metro lines to the picklist in the panel.
 */
function addLines() {
	// Picklist
	var picklist = document.getElementById('metro_lines');
	// Get metro lines from XML
	var lines = xml.getElementsByTagName('line');
	// Loop through lines and add them to the picklist
	for (var x = 0; x < lines.length; x++) {
		var line = getLineInfo(lines[x].getAttribute('id'));

		var elOption = document.createElement('option');
		var elText = document.createTextNode(line.name);
		elOption.appendChild(elText);
		elOption.value = line.id;
		picklist.appendChild(elOption);
	}
}


/*
 * Displays the stations in the panel.
 *
 * @param		selected_line (string) The selected metro line. Optional.
 */
function addStations(selected_line) {
	// Clear stations from panel
	$('#panel #list').empty();
	// Metro lines
	var lines = xml.getElementsByTagName('line');
	for (var x = 0; x < lines.length; x++) {
		// Get line info
		var line = getLineInfo(lines[x].getAttribute('id'));
		// Check for selected metro line(s)
		if (selected_line == line.id || selected_line == 'all' || !selected_line) {
			// Metro stops
			var stops = lines[x].getElementsByTagName('stop');
			for (var y = 0; y < stops.length; y++) {
				// Get station info
				var station = getStationInfo(stops[y].getAttribute('id'));
				// Add to metro station to panel list
				$('#panel #list').append(
					$('<p>'+station.name+'</p>')
						.attr('class', 'line_'+line.id+' station')
						.bind('click', station, function(args) {
							map.setCenter(
								new google.maps.LatLng(args.data.latitude, args.data.longitude)
							);
						})
						.bind('click', station, function(args) {
							displayInfoWindow(args.data);
						})
				);
			}
		}
	}
}


/*
 * Creates a marker on the map for a specific metro station.
 *
 * @param		station (object) The station information.
 */
function addMarker(station) {
	// Marker icon
	var icon = new google.maps.Icon();
	icon.image = './images/markers/circle_'+station.marker+'.png';
	icon.iconSize = new google.maps.Size(10, 10);
	icon.iconAnchor = new google.maps.Point(5, 5);
	// Add marker to map
	var point = new google.maps.LatLng(station.latitude, station.longitude);
	var marker = new google.maps.Marker(point, icon);
	map.addOverlay(marker);
	// Register click event for marker
	google.maps.Event.addListener(marker, 'click', function() {
		displayInfoWindow(station);
	});
}


/*
 * Creates a polyline between two stations.
 *
 * @param		lat_s (float) The latitude of the source station.
 * @param		lon_s (float) The longitude of the source station.
 * @param		lat_d (float) The latitude of the destination station.
 * @param		lon_d (float) The longitude of the destination station.
 * @param		color (string) The HEX color value of the line to draw.
 */
function addPolyline(lat_s, lon_s, lat_d, lon_d, color) {
	var polyline = new google.maps.Polyline(
		[new google.maps.LatLng(lat_s, lon_s),
		 new google.maps.LatLng(lat_d, lon_d)],
		color,
		8, // Thickness
		0.6 // Opacity
	);
	map.addOverlay(polyline);
}


/*
 * Retrieves the information about a metro line.
 *
 * @param		id (integer) The ID of the line.
 * @return	(object) The metro line information.
 */
function getLineInfo(id) {
	l = $('lines #'+id, xml);
	var line = {
		id: l.attr('id'),
		name: l.attr(lang),
		color: l.attr('color')
	}
	return line;
}


/*
 * Retrieves the information about a metro station.
 *
 * @param		id (integer) The ID of the station.
 * @return	(object) The metro station information.
 */
function getStationInfo(id) {
	s = $('stations #'+id, xml);
	var station = {
		id: s.attr('id'),
		name: s.find('name').text(),
		latitude: parseFloat(s.find('latitude').text()),
		longitude: parseFloat(s.find('longitude').text()),
		marker: s.find('marker').text(),
		url: s.find(lang).text()
	}
	return station;
}


/*
 * Displays an Info Window for a metro station.
 *
 * @param		station (object) A data map containing the station info.
 */
function displayInfoWindow(station) {
	// Latitude/Longitude
	var point = new google.maps.LatLng(station.latitude, station.longitude);
	// Google Static Maps
	var url = 'http://maps.google.com/maps/api/staticmap';
	url += '?markers=color:'+station.marker;
	url += '|'+station.latitude+','+station.longitude;
	url += '&size=398x200';
	url += '&maptype=hybrid';
	url += '&zoom=17';
	url += '&language='+language;
	url += '&sensor=false';
	// Create Info Window
	var html = '<div style="width: 400px; height: 300px;">';
	html += '<p><img src="/images/stations/'+station.id+'.png" /></p>';
	html += '<p><img src="'+url+'" style="border:1px solid #000;" /></p>';
	html += '<p><a href="'+station.url+'">'+moreInfo+'</a></p>';
	html += '</div>';
	map.openInfoWindowHtml(point, html);
}


/*
 * Switches metro lines when an option is selected in the picklist.
 */
function switchLine() {
	var line = $('#metro_lines option:selected').val();
	addOverlays(line);
	addStations(line);
}


/*
 * Resize the metro station list in the panel.
 */
function resizeList() {
	$("#panel #list").height(0); /* Fixes bug in IE/Win 6 & 7 */
	
	var height = $(window).height()
						 - $("#panel #header").height()
						 - $("#panel #footer").height()
						 - 40;
	$("#panel #list").height(height);
}
