/********************************************************
*********************************************************

Bones in Motion - BiM Active Map Tool for Google
Copyright 2006 by Bones in Motion - All Rights Reserved
January 2006 - Spencer Nassar - spencer@bim-inc.com

*********************************************************
********************************************************/

var map = null;						// primary map object
var	sessionID = null;				// Live Tracking session ID to use
var mapOffsetX = 0;					// amount to move map components on the screen - X
var mapOffsetY = 0;					// amount to move map components on the screen - Y
var mapType = 'G_NORMAL_MAP';		// map type to display
var	drewInitialData = false;		// true if we've drawn the data once; false if not
var	activityCompleted = false;		// true if we think the live tracking activity is finished; false if not
var	lastLinesArray = null;			// last set of live tracking event lines received from the server
var	refreshPoints = true;			// Once we graph a completed activity, don't replot the points until a major transition has occurred
var	lastPulseMarker = null;			// Last point which was a pulsing marker
var	lastPauseMarker = null;			// Last point which was a pause marker

var baseIcon = null;				// icons for map display
var startIcon = null;
var endIcon = null;
var dotbaseIcon = null;
var dotmarkerIcon = null;
var dotmarkerPulseIcon = null;
var pauseIcon = null;

// primary map init, called from the body "onload" tag when the page loads
function DoGMaps()
{
	// Get the session ID from the form
	sessionID = document.forms[0].sessionid.value;
	
	// Get the type of map to display
	mapType = document.forms[0].maptype.value;

	// Create the canned icons
	setupIcons();

	// Position the map appropriately
	adjustMapPosition();
	
	// Setup the map
	map = new GMap(document.getElementById('map'));
	map.addControl(new GLargeMapControl());
	map.addControl(new GMapTypeControl());

	// turn on terrain map option
	map.addMapType(G_PHYSICAL_MAP);

	// topo
	var custommap1 = 'G_NORMAL_MAP';
	if ( useGMapTopoFeature == 1)
	{
		var tileDRG= new GTileLayer(new GCopyrightCollection(""),1,17);
		tileDRG.myLayers='DRG';
		tileDRG.myFormat='image/jpeg';
		tileDRG.myBaseURL='http://www.terraserver-usa.com/ogcmap6.ashx?';
		tileDRG.getTileUrl=CustomGetTileUrl;
		var layer1=[tileDRG];
		custommap1 = new GMapType(layer1, G_SATELLITE_MAP.getProjection(), "Topo", G_SATELLITE_MAP);
		map.addMapType(custommap1);
	}

	// setup controls, type, and position
	if ( mapType == 'G_NORMAL_MAP' )
		mapTypeToken = G_NORMAL_MAP ;
	else if ( mapType == 'G_HYBRID_MAP' )
		mapTypeToken = G_HYBRID_MAP ;
	else if ( mapType == 'G_PHYSICAL_MAP' )
		mapTypeToken = G_PHYSICAL_MAP;
	else if ( mapType == 'G_SATELLITE_MAP' )
		mapTypeToken = G_SATELLITE_MAP ;
	else mapTypeToken = custommap1;
	map.setMapType(mapTypeToken);

	// Load the initial set of live tracking data
	reloadLiveTrackDataFromServer();
}


// ===== reloadLiveTrackDataFromServer =====
//
//	Pings the server to get the lastest set of live tracking data to graph.
//
function reloadLiveTrackDataFromServer()
{
	GDownloadUrl("http://" + document.domain + "/ba/ui/live_tracking_status.php?sessID=" + sessionID, 
				function(data, responseCode)
				{
					if ( responseCode == 200 ) 
					{
						refreshLiveTrackMapData(data);
					}
					
					// Setup the timer to be called again (refresh every minute)
					setTimeout('reloadLiveTrackDataFromServer()', 1 * 60000);
				}
				);
}
/* reloadLiveTrackDataFromServer */


// ===== refreshEntirePage =====
//
//	Called to reload the entire page when needed.
//
function refreshEntirePage()
{
	window.location.replace("http://" + document.domain + "/ba/ui/live_tracking.php?lt_sessionID=" + sessionID);
}
/* refreshEntirePage */


// ===== refreshLiveTrackMapData =====
//
//	Pings the server to get the lastest set of live tracking data to graph.
//
function refreshLiveTrackMapData(
	data)		//	(in)	string from server containing the live tracking events data on separate lines 
{
	var	linesArray = data.split("\n");
	var	numPoints = linesArray.length - 1;	//	Split adds an empty entry on the end
	var pointdata = null;
	var point = null;
	var	displayCenter = null;
	var routebounds = new GLatLngBounds();
	var	startDateTime = null;
	var	doLoadPoints = true;
	var	startPoint = null;
	var	startPointHTML = null;

	// Always assume it's not completed
	activityCompleted = false;
	
	// Look for transitions which require us to reload the entire page
	if ( (lastLinesArray != null) && (lastLinesArray.length > 1) && (numPoints > 0) )
	{
		var lastLinesLastPoint = lastLinesArray[0].split("\t");
		var currLinesLastPoint = linesArray[0].split("\t");
		
		// Did the activity just complete?
		if ( (lastLinesLastPoint[11] == 0) && (currLinesLastPoint[11] != 0) )
		{
			refreshEntirePage();
			doLoadPoints = false;
			refreshPoints = true;
			drewInitialData = false;
		}
		else
		if ( (lastLinesLastPoint[11] != 0) && (currLinesLastPoint[11] == 0) )	// Did the activity just start
		{
			refreshEntirePage();
			doLoadPoints = false;
			refreshPoints = true;
			drewInitialData = false;
		}
	}
	
	// Is this the first time ever the user has had live tracking events? If so, refresh the page
	if ( (linesArray.length > 1) && (document.forms[0].lt_num_events.value == 0) )
	{
		refreshEntirePage();
		doLoadPoints = false;
		refreshPoints = true;
		drewInitialData = false;
	}
	
	if (doLoadPoints && refreshPoints)
	{
		var		zOrderIdx = 1;

		// Is there any data?
		if (numPoints > 0)
		{
			// Is the activity completed?
			pointdata = linesArray[0].split("\t");
			activityCompleted = pointdata[11] != 0;
			
			// If auto-pan is turned off, then only add the last point to the map (if there is one)
			if ( !activityCompleted && ((document.forms[0].lt_autoPanMap == null) || !document.forms[0].lt_autoPanMap.checked) )
			{
				if (lastLinesArray != null)
				{
					// Did we receive a new point?
					if (linesArray.length > lastLinesArray.length)
					{
						// Just add the most recent point to the map
						
						// Remove any old pulsing or pause markers
						if (lastPulseMarker != null)
						{
							map.removeOverlay(lastPulseMarker);
							lastPulseMarker = null;
						}
						
						if (lastPauseMarker != null)
						{
							map.removeOverlay(lastPauseMarker);
							lastPauseMarker = null;
						}
						
						// Split up the fields in the next line
						pointdata = linesArray[0].split("\t");
						
						// A good line?
						if ( pointdata.length >= 13 )
						{
							// Create a point object
							point = new GLatLng(parseFloat(pointdata[1]), parseFloat(pointdata[2]));
							
							// Add a new pulse point
							lastPulseMarker = createDotMarker(point, makeMarkerInfoWindowHTMLString(pointdata), dotmarkerPulseIcon, linesArray.length);
							map.addOverlay(lastPulseMarker);

							if ( parseInt(pointdata[12]) == 100)
							{
								lastPauseMarker = createDotMarker(point, makeMarkerInfoWindowHTMLString(pointdata), pauseIcon, linesArray.length + 1);
								map.addOverlay(lastPauseMarker);
							}

							// Update the stats in the window
							document.getElementById("info_enddate").innerHTML = pointdata[0];
							document.getElementById("info_stats_time").innerHTML = pointdata[9];
							document.getElementById("info_stats_distance").innerHTML = pointdata[4];
							document.getElementById("info_stats_pace").innerHTML = pointdata[6];
							document.getElementById("info_stats_speed").innerHTML = pointdata[5];
						}

						// Replace the last point to be non-pulsing
						
						// Split up the fields in the next line
						pointdata = lastLinesArray[0].split("\t");
						
						// A good line?
						if ( pointdata.length >= 13 )
						{
							// Create a point object
							point = new GLatLng(parseFloat(pointdata[1]), parseFloat(pointdata[2]));
							
							// Add a new point for the old point
							map.addOverlay( createDotMarker(point, makeMarkerInfoWindowHTMLString(pointdata), dotmarkerIcon, lastLinesArray.length) );
						}
					}
				}
			}
			else	// Always re-layout the entire map
			{
				// Remove any previous markers
				map.clearOverlays();
				lastPulseMarker = null;
				lastPauseMarker = null;

				// For some reason map.centerAndZoom must be called first otherwise map.addOverlay will fail
				map.setCenter(new GLatLng(0, 0), 0);
		
				// Draw the points
				for (var i = (numPoints - 1); i >= 0; i--)
				{
					// Split up the fields in the next line
					pointdata = linesArray[i].split("\t");
					
					// A good line?
					if ( pointdata.length < 13 )
					{
						continue;
					}
					
					// Create a point object
					var	lat = parseFloat(pointdata[1]);
					var	lon = parseFloat(pointdata[2]);
					
					point = new GLatLng(lat, lon);
		
					// Extend the bounds of the rectangle which surrounds all points
					routebounds.extend(point);
					
					// Create and add appropriate markers to the map
					if (i == 0)
					{
						// Is the activity completed?
						if ( activityCompleted )
						{
							// Create and add the marker
							map.addOverlay( createDotMarker(point, makeMarkerInfoWindowHTMLString(pointdata), dotmarkerIcon, zOrderIdx++) );
							
							// Show the start point
							if (numPoints == 1)
							{
								map.addOverlay( createDotMarker(point, makeMarkerInfoWindowHTMLString(pointdata), startIcon, zOrderIdx++) );
							}
							else	// Show the start point on top
							{
								map.addOverlay( createDotMarker(startPoint, startPointHTML, startIcon, zOrderIdx++) );
							}
							
							// Also add the end marker
							map.addOverlay( createDotMarker(point, makeMarkerInfoWindowHTMLString(pointdata), endIcon, zOrderIdx++) );
						}
						else	// Activity still going
						{
							// Create and add the marker
							lastPulseMarker = createDotMarker(point, makeMarkerInfoWindowHTMLString(pointdata), dotmarkerPulseIcon, zOrderIdx++);
							map.addOverlay(lastPulseMarker);
		
							if (numPoints == 1)
							{
								// Also add the start marker
								map.addOverlay( createDotMarker(point, makeMarkerInfoWindowHTMLString(pointdata), startIcon, zOrderIdx++) );
							}
							else	// Show the start point on top
							{
								if ( parseInt(pointdata[12]) == 100)
								{
									lastPauseMarker = createDotMarker(point, makeMarkerInfoWindowHTMLString(pointdata), pauseIcon, zOrderIdx++);
									map.addOverlay(lastPauseMarker);
								}

								map.addOverlay( createDotMarker(startPoint, startPointHTML, startIcon, zOrderIdx++) );
							}
						}
						
						// Center the map around the most recent point
						displayCenter = point;
						
						// Update the stats in the window
						if (numPoints == 1)
						{
							document.getElementById("info_startdate").innerHTML = pointdata[0];
						}
						else
						{
							document.getElementById("info_startdate").innerHTML = startDateTime;
						}
		
						document.getElementById("info_enddate").innerHTML = pointdata[0];
						document.getElementById("info_stats_time").innerHTML = pointdata[9];
						document.getElementById("info_stats_distance").innerHTML = pointdata[4];
						document.getElementById("info_stats_pace").innerHTML = pointdata[6];
						document.getElementById("info_stats_speed").innerHTML = pointdata[5];
					}
					else
					if ( (i + 1) == numPoints )	//	Last point in sequence which is the first point in the path
					{
						// Create and add the marker
						map.addOverlay( createDotMarker(point, makeMarkerInfoWindowHTMLString(pointdata), dotmarkerIcon, zOrderIdx++) );
						
						// Remember where the data started
						startPoint = point;
						startPointHTML = makeMarkerInfoWindowHTMLString(pointdata);
						
						// Remember the start time of the activity
						startDateTime = pointdata[0];
					}
					else	// Some point in the middle of the path
					{
						// Create and add the marker
						map.addOverlay( createDotMarker(point, makeMarkerInfoWindowHTMLString(pointdata), dotmarkerIcon, zOrderIdx++) );
					}
				}
		
				// Center the map and set the zoom level. Only set the zoom level once initially
				if ( !drewInitialData )
				{
					// Set the center and zoom
					map.setZoom( map.getBoundsZoomLevel(routebounds) );
					map.setCenter( routebounds.getCenter() );
					drewInitialData = true;
					
					// Don't draw anymore until another major transition
					if (activityCompleted)
					{
						refreshPoints = false;
					}
				}
				else
				if ( !activityCompleted )
				{
					// See if we should auto-pan the map
					if ( (document.forms[0].lt_autoPanMap != null) && document.forms[0].lt_autoPanMap.checked )
					{
						// Set the center and zoom
						map.setZoom( map.getBoundsZoomLevel(routebounds) );
						map.setCenter( routebounds.getCenter() );
					}
				}
				else
				{
					map.setZoom( map.getBoundsZoomLevel(routebounds) );
					map.setCenter( routebounds.getCenter() );
					
					// Don't refresh points until another major transition
					refreshPoints = false;
				}
			}
		}
		else	// No points, show a world view
		{
			map.centerAndZoom(new GLatLng(30, -80), 15);	// World Map View!
		}
	}
	
	// Remember the last lines array
	if (numPoints > 0)
	{
		lastLinesArray = linesArray;
	}
}
/* refreshLiveTrackMapData */


// ===== makeMarkerInfoWindowHTMLString =====
//
//	Creates and returns the html string that's displayed in the marker popup bubble.
//
function makeMarkerInfoWindowHTMLString( 
	pointdata)			//	(in)	array containing the point data with the following values in the array offsets:
						//			[0] - local timstamp string
						//			[1] - latitude string
						//			[2]	- longitude string
						//			[3]	- altitude string
						//			[4]	- distance string
						//			[5]	- speed string
						//			[6]	- pace string
						//			[7]	- last split speed string
						//			[8]	- last split pace string
						//			[9]	- total time string
						//			[10]- calories string
						//			[11]- completed activity (1 if completed 0 if not)
{
	var html = '';

	html = '<font size=2 color=#333333><table border=0 cellpadding=0 cellspacing=3>';
	
	html = html + '<tr align=center><td colspan=5><b>' + pointdata[0] + '</b></td></tr>';

	html = html + '<tr valign=top><td colspan=4>&nbsp;</td><td><i>Average</i></td></tr>';
	
	html = html + '<tr valign=top><td align=right>Time:</td><td align=left><b>' +  pointdata[9] + '</b></td>';
	html = html + '<td width=15>&nbsp;</td><td align=right>Pace:</td><td align=left><b>' +  pointdata[6] + '</b></td></tr>';
	
	html = html + '<tr valign=top><td align=right>Distance:</td><td align=left><b>' +  pointdata[4] + '</b></td>';
	html = html + '<td width=15>&nbsp;</td><td align=right>Speed:</td><td align=left><b>' +  pointdata[5] + '</b></td></tr>';

	html = html + '<tr valign=top><td align=right>Calories:</td><td align=left><b>' + ((pointdata[10] == 0) ? '--' : pointdata[10]) + '</b></td>';
	html = html + '<td colspan=3>&nbsp;</td></tr>';
	
	html = html + '<td colspan=4>&nbsp;</td><td><i>Last Split</i></td></tr>';
	
	html = html + '<tr valign=top><td align=right>Lat:</td><td align=left><b>' +  pointdata[1] + '</b></td>';
	html = html + '<td width=15>&nbsp;</td><td align=right>Pace:</td><td align=left><b>' +  pointdata[8] + '</b></td></tr>';
	
	html = html + '<tr valign=top><td align=right>Lon:</td><td align=left><b>' +  pointdata[2] + '</b></td>';
	html = html + '<td width=15>&nbsp;</td><td align=right>Speed:</td><td align=left><b>' +  pointdata[7] + '</b></td></tr>';
	
	html = html + '</table></font>';

	return html;
}
/* makeMarkerInfoWindowHTMLString */


// ===== createDotMarker =====
//
//	Creates a new dot marker and sets up its html bubble text.
//
function createDotMarker(
	point, 					//	(in)	point where marker should appear
	markerString,			//	(in)	marker html string
	markerIcon,				//	(in)	icon to use for display of the marker
	zOrderIdx)				//	(in)	z-order index of this item
{
	var marker =  new GMarker(point, {icon: markerIcon, zIndexProcess: function(marker) {return marker.zOrderIdx;}});

	// Set the z-order index
	marker.zOrderIdx = zOrderIdx;
	
	marker.clickListener = GEvent.addListener(	marker, 
												"click", 
												function()
												{
													marker.openInfoWindowHtml(markerString, {});
												}
											);

	return marker;
}
/* createDotMarker */
