var gClickMapEvent;
var mapMarkersArray = new Array();			// map marker data
var mapLinesArray = new Array();			// map route (polyline) line data. Each element contains an array of lat/lon co-ordinates (route - array of element indexes corresponding to markers starting at 1 - read top to bottom of file), line width (width - integer), and  line color (color - HTML RGB value)
var mapControlDataArray = new Array();		// control data (zoom, central point, map title,...)
mapControlDataArray["mapTitle"] = 'Interactive Map';
mapControlDataArray["mapWidth"] = 800;
mapControlDataArray["defaultWidth"] = 180;
mapControlDataArray["defaultHeight"] = 135;
mapControlDataArray["centralLatitude"] = 42.27769;
mapControlDataArray["centralLongitude"] = -83.75603;
mapControlDataArray["zoom"] = 5;	// higher number means closer view; at 600px wide, 7 = width of New Mexico, 12 = San Francisco
mapControlDataArray["icon"] = "googlemini";
mapControlDataArray["color"] = "red";
mapControlDataArray['imagePath'] = "";	// paths are based on the directory of the enclosing map pages.
mapControlDataArray['linkPath'] = "";	// paths are based on the directory of the enclosing map pages.
mapControlDataArray['controls'] = "all";	// has map controls; false if they're to be not shown
mapControlDataArray['maptype'] = 'G_HYBRID_MAP';
mapControlDataArray['showLocation'] = false;

var overrideFileData = new Array();	
overrideFileData.mapTitle = false;
overrideFileData.width = false;
overrideFileData.lat = false;
overrideFileData.lon = false;
overrideFileData.legend = false;
overrideFileData.personalize = false;
overrideFileData.zoom = false;
overrideFileData.controls = false;
overrideFileData.title = false;

function Map_MakeImageAndLink(str)
/* 	Return a description string modified with hyperlink and image code.
	The function looks for "<image></image>", "<imageleft></imageleft>", and "<link></link>" tags
	and acts accordingly.
	
	<image> 		Creates straight <img> tag
	<imageleft>		Creates an <img> tag that is floated left.
	<imageleft*>	Creates an <img> tag that is floated left but doesn't clear.
	<imageleft+>	Creates an <img> tag that is floated left and doesn't define WIDTH and HEIGHT.
	<imageright>	Creates an <img> tag that is floated right.
	<imageright*>	Creates an <img> tag that is floated right but doesn't clear.
	<imageleft dir>	Create <img> tag floated left using value from 'dir' as base bath.

	<image float width height dir>	Create <img> using 'dir' base path, 'float' value, 
									and 'width' and 'height dimensions - order is important and at
									present all values must be specified.

	<link>			Creates an <a> tag with a class of "maplink".
	<link text>		Create an <a> and use 'text' as the display text instead of the default text.
	<fulllink>		Creates an <a> tag with a class of "maplink". Ingore the default link path.
	<fulllink text>	Create an <a> and use 'text' as the display text instead of the default text. Ingore the default link path.
	<plink>, <pfulllink>	Act the same as <link> and <fulllink> but open in parent window (for iframe support)
	str:	Required string. Description string from a gpsvisualizer marker object.
*/
{
	var newStr = new String(str);

	var imgStartTag = "<img width='" + mapControlDataArray['defaultWidth'] + "' height='" + mapControlDataArray['defaultHeight'] +"' 'alt='' src='" + mapControlDataArray['imagePath'];
	var imgleftStartTag = "<img style='clear: both; float: left; padding-right: 3px; padding-top: 5px' width='" + mapControlDataArray['defaultWidth'] + "' height='" + mapControlDataArray['defaultHeight'] +"' 'alt='' src='" + mapControlDataArray['imagePath'];
	var imgleftstarStartTag = "<img style='float: left; padding-left: 3px; padding-right: 3px; padding-top: 5px' width='" + mapControlDataArray['defaultWidth'] + "' height='" + mapControlDataArray['defaultHeight'] +"' 'alt='' src='" + mapControlDataArray['imagePath'];
	var imgleftplusStartTag = "<img style='float: left; padding-left: 3px; padding-right: 3px; padding-top: 5px' alt='' src='" + mapControlDataArray['imagePath'];

	var imgrightStartTag = "<img style='clear: both; float: right; padding-left: 3px; padding-top: 5px' width='" + mapControlDataArray['defaultWidth'] + "' height='" + mapControlDataArray['defaultHeight'] +"' 'alt='' src='" + mapControlDataArray['imagePath'];
	var imgrightstarStartTag = "<img style='float: right; padding-left: 3px; padding-right: 3px; padding-top: 5px' width='" + mapControlDataArray['defaultWidth'] + "' height='" + mapControlDataArray['defaultHeight'] +"' 'alt='' src='" + mapControlDataArray['imagePath'];

	var imgEndTag = ".jpg'>";

	var linkStartTag = "<a class='maplink' href='" + mapControlDataArray['linkPath'] ;
	var plinkStartTag = "<a class='maplink' target='_parent' href='" + mapControlDataArray['linkPath'] ;
	var fulllinkStartTag = "<a class='maplink' target='_parent' href='" ;
	var pfulllinkStartTag = "<a class='maplink' target='_parent' href='"  ;
	var linkEndTag = "'>Visit this link</a>";
	
// search/replace start and end tags.
	newStr = newStr.replace(/<image>/gi, imgStartTag);
	newStr = newStr.replace(/<imageleft>/gi, imgleftStartTag);
	newStr = newStr.replace(/<imageleft\*>/gi, imgleftstarStartTag);
	newStr = newStr.replace(/<imageleft\+>/gi, imgleftplusStartTag);
	newStr = newStr.replace(/<imageright>/gi, imgrightStartTag);
	newStr = newStr.replace(/<imageright\*>/gi, imgrightstarStartTag);
	newStr = newStr.replace(/<image (.*?) (.*?) (.*?) (.*?)>/gi, 
							"<img alt='' style='float: $1 ; padding-left: 3px; padding-right: 3px; padding-top: 5px' width='$2' height='$3' src='$4");
	newStr = newStr.replace(/<\/image>/gi, imgEndTag);
	newStr = newStr.replace(/<\/imageleft>/gi, imgEndTag);
	newStr = newStr.replace(/<\/imageleft\*>/gi, imgEndTag);
	newStr = newStr.replace(/<\/imageleft\+>/gi, imgEndTag);
	newStr = newStr.replace(/<\/imageright>/gi, imgEndTag);
	newStr = newStr.replace(/<\/imageright\*>/gi, imgEndTag);

	newStr = newStr.replace(/<link>/gi, linkStartTag);
	newStr = newStr.replace(/<plink>/gi, plinkStartTag);
	newStr = newStr.replace(/<fulllink>/gi, fulllinkStartTag);
	newStr = newStr.replace(/<pfulllink>/gi, pfulllinkStartTag);
	newStr = newStr.replace(/<link (.*?)>(.*?)<\/link>/gi, linkStartTag + "$2'>$1<\/a>");
	newStr = newStr.replace(/<plink (.*?)>(.*?)<\/plink>/gi, plinkStartTag + "$2'>$1<\/a>");
	newStr = newStr.replace(/<fulllink (.*?)>(.*?)<\/fulllink>/gi, fulllinkStartTag + "$2'>$1<\/a>");
	newStr = newStr.replace(/<pfulllink (.*?)>(.*?)<\/pfulllink>/gi, pfulllinkStartTag + "$2'>$1<\/a>");
	newStr = newStr.replace(/<\/link>/gi, linkEndTag);
	newStr = newStr.replace(/<\/plink>/gi, linkEndTag);
	newStr = newStr.replace(/<\/fulllink>/gi, linkEndTag);
	newStr = newStr.replace(/<\/pfulllink>/gi, linkEndTag);

//	newStr = newStr.replace(/\. /g, ".<br>");

	return newStr;
} // Map_MakeImageAndLink

function Map_TranslateDescriptionStrings(mm)
/*	Modify the description strings for all mapMarkers in the array.
	
	mm.	Required Array. The mapMarkers array of gpsvisualizer marker objects.
*/
{
	for (i = 0; i < mm.length; i++ ) {
		mm[i]['desc'] = Map_MakeImageAndLink(mm[i]['desc']);
		if (mapControlDataArray['showLocation'] == true) {
			mm[i]['name'] = mm[i]['name'] + "<br>latitude: " + mm[i]['lat'] + "&deg;N, longitude: " + mm[i]['lon'] + "&deg;E";
		}
	}
	
	mm;
} // Map_TranslateDescriptionStrings

function LoadMap()
/* Gets the map data and then creates the map. */
{
	var baseUrl = "http://www.wanderingknight.org/travels/";
	var mapWidth = 300;
	var mapHeight = 245;
	var mapControls = "small";
	var mapType = 'G_HYBRID_MAP';
	var mapZoom = "12";
	var centralLat;
	var centralLon;
//	var notFromFile = false;					// Default. Data comes from file on server. 
	var noTitle = false;
	var tempUrl = window.location.search;
	var url = baseUrl + escape("mapMarkers");
	var dataInFile = false;
	var waypointsData = false;
	
	if ( browserIsCompatible ) {
		tempUrl = tempUrl.substr(1);
	
		var params = tempUrl.split("&");					// first break up variable/value pairs
		for (i=0; i < params.length; i++) {
			var propertyAndValue = params[i].split("=");			// a variable and its value
			switch (propertyAndValue[0]) {
				case "legend":
					mapControlDataArray["legend"] = propertyAndValue[1];
					var mapLegend = propertyAndValue[1];
					overrideFileData.legend = true;
					break;
				case 'personalize':
					mapControlDataArray["personalize"] = unescape(propertyAndValue[1]);
					var mapPersonalize = unescape(propertyAndValue[1]);
					overrideFileData.personalize = true;
//					document.getElementById("personalizeLegend").innerHTML = unescape(propertyAndValue[1]);
					break;
				case "lat":
					centralLat = propertyAndValue[1];
					overrideFileData.lat = true;
//					notFromFile = true;
					break;
				case "lon":
					centralLon = propertyAndValue[1];
					overrideFileData.lon = true;
//					notFromFile = true;
					break;
				case "controls":
					mapControls = propertyAndValue[1];
					overrideFileData.controls = true;
//					notFromFile = true;
					break;
				case "maptype":		// valid strings: USGS_AERIAL_TILES, USGS_TOPO_TILES, G_HYBRID_MAP, G_SATELLITE_MAP, G_NORMAL_MAP, NRCAN_TOPO_TILES, BLUEMARBLE_TILES, DAILY_TERRA_TILES, DAILY_AQUA_TILES
					try {
						mapType = propertyAndValue[1];
					} catch (e) {
						alert("Unknown map type: " + propertyAndValue[1] + "\rError: " + e);
					}
					overrideFileData.mapType = true;
					break;
				case "zoom":
					mapZoom = propertyAndValue[1];
					overrideFileData.zoom = true;
//					notFromFile = true;
					break;
				case "title":
					noTitle = (propertyAndValue[1] == "true") ? true : false;
					overrideFileData.title = true;
//					notFromFile = true;
					break;
				case "width":
					mapWidth = propertyAndValue[1];
					mapControlDataArray['mapWidth'] = mapWidth;
					mapHeight = (mapWidth * 0.75) + 20;
					overrideFileData.width = true;
//					notFromFile = true;
					break;
				case "map":
					url = baseUrl + escape(propertyAndValue[1]);
					dataInFile = true;
					break;
				case "waypoints":
					waypointsURL = baseUrl + escape(propertyAndValue[1]);
					waypointsData = true;
					break;
			}
		}
	
		if ( dataInFile  ) {				// i.e., data is in a file
			xmlhttpPost(url, "", "ProcessMapData");
			mapControlDataArray['lat'] =  (overrideFileData.lat == true) ? centralLat : mapControlDataArray['lat'];
			mapControlDataArray['lon'] =  (overrideFileData.lon == true) ? centralLon : mapControlDataArray['lon'];
			mapControlDataArray['legend'] =  (overrideFileData.legend == true) ? mapLegend : mapControlDataArray['legend'];
			mapControlDataArray['personalize'] =  (overrideFileData.personalize == true) ? mapPersonalize : mapControlDataArray['personalize'];
			mapControlDataArray['controls'] =  (overrideFileData.controls == true) ? mapControls : mapControlDataArray['controls'];
			mapControlDataArray['maptype'] =  (overrideFileData.mapType == true) ? mapType : mapControlDataArray['maptype'];
			mapControlDataArray['zoom'] =  (overrideFileData.zoom == true) ? mapZoom : mapControlDataArray['zoom'];
//			mapControlDataArray['mapTitle'] =  (overrideFileData.noTitle == true) ? noTitle : mapControlDataArray['noTitle'];
			mapControlDataArray['mapWidth'] =  (overrideFileData.width == true) ? mapWidth : mapControlDataArray['mapWidth'];
		} else {
			str = "data = zoom: " + mapZoom +  "\ndata = controls: '" + mapControls + "'\ndata = maptype: " + mapType + "\n";
			if (centralLat && centralLon) {
				str = str + "\ndata = centralLatitude: " + centralLat + "\ndata = centralLongitude: " + centralLon + "\n";
				str = str + "marker = { lat: " + centralLat + ", lon: " + centralLon + ", name: 'marker', desc: '', color: 'red' }\n";
			}
	
			document.getElementById("gmap_div").style.height = mapHeight - 20 + "px";
			document.getElementById("gmap_div").style.width = mapWidth + "px"
			document.getElementById("outermap").style.height = mapHeight + "px";

			if (noTitle == true ) {
				document.getElementById("interactiveMapTitle").style.display = "none";
			} else {
				document.getElementById("interactiveMapTitle").style.display = "block";
			}
			ProcessMapData(str);
		}
		if ( waypointsData  ) {				// i.e., data is in a file
			xmlhttpPost(waypointsURL, "", "ProcessMapData");
		}
	}
} // LoadMap

function xmlhttpPost(strURL, strSubmit, strResultFunc) {
	var xmlHttpReq = false;
	
	// Mozilla/Safari
	if (window.XMLHttpRequest) {
			xmlHttpReq = new XMLHttpRequest();
			xmlHttpReq.overrideMimeType('text/plain');
	}
	// IE
	else if (window.ActiveXObject) {
			xmlHttpReq = new ActiveXObject("Microsoft.XMLHTTP");
	}
	
	xmlHttpReq.open('GET', strURL, true);
	xmlHttpReq.setRequestHeader('Content-Type', 'text/plain');
		xmlHttpReq.onreadystatechange = function() {
			if ( (xmlHttpReq.readyState == 1) || (xmlHttpReq.readyState == 2)) {			// data loading
			}
			if (xmlHttpReq.readyState == 4) {			// data all loaded
				strResponse = xmlHttpReq.responseText;
				switch (xmlHttpReq.status) {
				case 404:		// Page-not-found error
					alert('Error: Map Not Found. The requested map (url) ' + 
						strURL + ' could not be found.');
						break;
				   case 500:	// Display results in a full window for server-side errors
						handleErrFullPage(strResponse);
						break;
					default:	// Call JS alert for custom error or debug messages
						if (strResponse.indexOf('Error:') > -1 || 
							strResponse.indexOf('Debug:') > -1) {
							alert(strResponse);
						} else {	// Call the desired result function
							eval(strResultFunc + '(strResponse);');
						}
							break;
			   }
			}
		}
	xmlHttpReq.send(strSubmit);
} // xmlhttpPost

function handleErrFullPage(strIn) {
	var errorWin;
	// Create new window and display error
	try {
		errorWin = window.open('', 'errorWin');
		errorWin.document.body.innerHTML = strIn;
	}
	// If pop-up gets blocked, inform user
	catch(e) {
		alert('An error occurred, but the error message cannot be' +
		' displayed because of your browser\'s pop-up blocker.\n' + 'Please allow pop-ups from this Web site.');
	}
} // handleErrFullPage

	
function ProcessMapData(theData)
/*	Called asynchronously by xmlhttpPost to process the received data - map marker points.
	
	theData:	Required. String. String of data, the map marker points.
*/
{
	var hasErrors = false;
	var errors = "";
	
	var nineMoths = 23655691293;

	var theDataArray = theData.split("\n");
	for (i = 0; i < theDataArray.length; i++ ) {
		temp = theDataArray[i].split( " = ");	// get data
		try {
				if ( temp[0] == "marker" ) {	// Map Marker point?
					eval("mapMarkersArray[mapMarkersArray.length] = " + temp[1] +";");
				} else if (temp[0] == "line") {	// Map route line?
					eval("mapLinesArray[mapLinesArray.length] = " + temp[1] +";");
				} else if ( temp[0] == "data")  {						// Other type of data for the map or webpage.
					temp1 = temp[1].split(": ");
					mapControlDataArray[ temp1[0] ] = eval( "{" + temp1[1] + "};" );
				}
		} catch (e) {
			errors = errors + "data item: " + (i+1) + " error: "+ e + "\n";
			hasErrors = true;
		}
	}

	// Change color if the markers cotnains trips that are less than nine months old.
	for (i = 0; i < mapMarkersArray.length; i++ ) {
		if ( mapMarkersArray[i].date ) {
			if ( new Date() - new Date(mapMarkersArray[i].date) <= nineMoths ) {
				mapMarkersArray[i].color = 'yellow';
			}
		}
	}
	
	// Now create the map.
	var mapWidth = mapControlDataArray['mapWidth'];
	var mapHeight = mapWidth * 0.75;
	document.getElementById("gmap_div").style.height = mapHeight - 20 + "px";
	document.getElementById("gmap_div").style.width = mapWidth + "px"
	document.getElementById("outermap").style.height = mapHeight + "px";

	document.getElementById("interactiveMapTitle").innerHTML = mapControlDataArray["mapTitle"];
	if (mapControlDataArray["personalize"] != null) {
		document.getElementById("personalizeLegend").innerHTML = mapControlDataArray["personalize"];
	}
	switch (mapControlDataArray["legend"]) {
		case "none":
			document.getElementById("wholeLegend").style.display = "none";
			break;
		case "all":
			document.getElementById("wholeLegend").style.display = "block";
			document.getElementById("allIcons").style.display = "block";
			break;
		case "text":
			document.getElementById("wholeLegend").style.display = "block";
			document.getElementById("allIcons").style.display = "none";
			break;
	}

	gv_marker_icon = mapControlDataArray["icon"];
	Map_TranslateDescriptionStrings(mapMarkersArray);	// Process <image> and <link> tags.
	GV_Map();
	if ( hasErrors ) {
		alert("Some errors ocurred while loading the map. Here is a list of problem items.\n" + errors);
	}
} // ProcessMapData

function GV_Map() {
	if (GBrowserIsCompatible()) { 

		gmap = new GMap2(document.getElementById("gmap_div")); // create map
	
		gmap.setCenter(new GLatLng(mapControlDataArray['centralLatitude'], mapControlDataArray['centralLongitude']), mapControlDataArray['zoom'], eval(mapControlDataArray['maptype']));
		gClickMapEvent = GEvent.addListener(
							gmap, 
							"click", 
							function(overlay, point) {
								var thePoint = (overlay == null) ? point.toString() : overlay.getLatLng();
								document.getElementById("coordinates").innerHTML = thePoint;
							}
						);
		document.getElementById("coordinates").innerHTML = gmap.getCenter();
		
		switch (mapControlDataArray['controls']) {
			case "all": 
				gmap.addControl(new GV_MapTypeControl()); // add custom map type switcher
				gmap.addControl(new GLargeMapControl());
				gmap.addControl(new GScaleControl());
				break;
			case "small":
				gmap.addControl(new GV_MapTypeControl()); // add custom map type switcher
				gmap.addControl(new GSmallMapControl());
				gmap.addControl(new GScaleControl());
				break;
			case "menu":
				gmap.addControl(new GV_MapTypeControl()); // add custom map type switcher
				gmap.addControl(new GScaleControl());
				break;
			case "none":
				gmap.addControl(new GScaleControl());
				break;
		}
		_mSvgEnabled = true; _mSvgForced = true;
		
		// Gather map markers (waypoints) from the mapMarkers array.
		for (i=0; i < mapMarkersArray.length; i++ ) {
			if ( ( !(mapMarkersArray[i].hide)) || ( mapMarkersArray[i].hide == false) ) {
				temp = GV_Marker(gmap, mapMarkersArray[i] );
			}
		}

		// Make polylines - if any
		
		
		for (i=0;i < mapLinesArray.length; i++ ) {
			var indexMethod = "id";
			switch (mapLinesArray[i].key) {
				case "id": 
					indexMethod = "id";
					break;
				case "index": 
					indexMethod = "index";
					break;
				case "range": 
					indexMethod = "range";
					break;
			}
			var theLine = new Array();
			if ( (indexMethod == "index") || (indexMethod == "id") ) {
				for (j=0;j < mapLinesArray[i].route.length; j++) {
					if (indexMethod == "index") {
						theLine.push( new GLatLng(mapMarkersArray[ mapLinesArray[i].route[j] - 1].lat,mapMarkersArray[ mapLinesArray[i].route[j] - 1].lon));
					} else {
						for (k=0;k < mapMarkersArray.length; k++ ) {
							if (mapLinesArray[i].route[j] == mapMarkersArray[k].id) {
								theLine.push( new GLatLng(mapMarkersArray[k].lat, mapMarkersArray[k].lon));
								break;
							}
						}
					} 
				}
			} else {		// use range
				for (j=mapLinesArray[i].route[0];j <= mapLinesArray[i].route[1]; j++ ) {
					for (k=0;k < mapMarkersArray.length; k++ ) {
						if (mapMarkersArray[k].id == j) {
							if (mapMarkersArray[k].id == j) {
								theLine.push( new GLatLng(mapMarkersArray[k].lat, mapMarkersArray[k].lon));
								break;
							}
						}
					}
				}
			}
			
			if ( (!(mapLinesArray[i].processed) || (mapLinesArray[i].processed == false)) && (!(mapLinesArray[i].visible)) || (mapLinesArray[i].visible == "yes")) {
				mapLinesArray[i].theLine = new GPolyline(theLine, mapLinesArray[i].color, mapLinesArray[i].width) ;
				mapLinesArray[i].theLine = gmap.addOverlay( new GPolyline(theLine, mapLinesArray[i].color, mapLinesArray[i].width) );
				mapLinesArray[i].processed = true;
			}
		}		
		// Change TITLE to reflect the name of the map.
		if ( document.getElementsByTagName ) {
			document.getElementsByTagName("title")[0].innerText = mapControlDataArray['mapTitle'];
		}
		gmap.addMapType(G_SATELLITE_3D_MAP);
	} else {
		document.getElementById('gmap_div').style.backgroundColor = '#DDDDDD';
		document.getElementById('gmap_div').innerHTML = 'Sorry, your Google Map cannot be displayed.';
	}
} // GV_Map

function show_props(obj, obj_name, asHTML, withType) {
	var result = "";
	for (var i in obj) {
  	if ( asHTML == true ) {
			result += "<p>" + obj_name + "." + i + " = " + obj[i] + " ";
			if ( withType == true ) {
				result += "object type = " + typeof(obj[i]) + "</p>";
			}
		} else {
			result += obj_name + "." + i + " = " + obj[i] + " ";
			if ( withType == true ) {
				result += "object type = " + typeof(obj[i]) + " ";
			}
		}
	}
	return result;
} // show_props

