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

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 clickPolylines = Array();		// array of clickPolyline
var clickPolyline = Array();		// a GPolyline
var clickData = Array();			// info for the editable path - set of [lat, lon, cumulative distance]
var clickStartMarker = null;		// GMarker for the start of a user drawn route
var clickEndMarker = null;			// GMarker for the end of a user drawn route
var pathEditable = false;			// OK to edit clickPolyline?
var pathDirty = false;				// Path set dirty by server (wants data back always)
var pathDirtyLocal = false;			// Has path been edited?
var overlaysEditable = false;		// OK to edit overlays?
var overlaysDirty = false;			// Have overlays been edited?
var editMode = 'off';				// off, line, water, food, view, bathroom, parking, other, photo
var latData = null;					// raw lat data array from form
var lonData = null;					// raw lat data array from form
var ecodeData = null;				// raw error code data array from form
var haveEcode = null;				// ecodes present in data
var lastDataIndex = null;
var	pathArraySet = Array();			// set of any/all drawable GPolyline
var pauseMarkerArray = Array();		// pause marker set of GMarker
var resumeMarkerArray = Array();	// resume marker set of GMarker
var markerData = Array();			// marker item info
var markersDirty = false;			// markers set dirty by server
var markersDirtyLocal = false;		// markers have been changed
var markersEditable = false;		// markers can be edited
var formDistField = null;			// form field to set distance in
var distUnitsField = null;			// form checkbox to turn distance reporting on
var shouldShowSave = false;			// should save button appear when dirty?
var lastInfoMsgIdent = '';			// hold current info message when we switch out for hover
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	mileMarkers = Array();			// array of mile markers to display along the path

var baseIcon = null;				// icons for map display
var startIcon = null;
var endIcon = null;
var startendIcon = null;
var pauseIcon = null;
var resumeIcon = null;
var waterIcon = null;
var viewIcon = null;
var foodIcon = null;
var bathroomIcon = null;
var parkingIcon = null;
var otherIcon = null;

// primary map init, called from the body "onload" tag when the page loads
function DoGMaps()
{
	// import the form data
	var mapTypeToken;
	shouldShowSave = ( document.forms[0].showsave.value == "1" ) ? true : false;
	formDistField = document.forms[0].distancefield.value;
	distUnitsField = document.forms[0].distunitsfield.value;
	mapType = document.forms[0].maptype.value;
	latData = document.forms[0].lat_vals.value.split(",");
	lonData = document.forms[0].lon_vals.value.split(",");
	ecodeData = document.forms[0].ecode_vals.value.split(",");
	markersEditable = (document.forms[0].markerseditable.value == "1") ? true : false;
	pathEditable = (document.forms[0].patheditable.value == "1") ? true : false;

	var markerRawData = document.forms[0].markers.value.split(";");

	if ( markerRawData.length == 1 && markerRawData[0].length < 8 )
		markerRawData = Array();
	var temp = null;
	for (var i=0; i < markerRawData.length; i++ ) {
		temp = markerRawData[i].split(",");
		if (temp.length == 5)
			markerData.push( { "type": temp[0], "lon": parseFloat(temp[1]), "lat": parseFloat(temp[2]), "label": temp[3], "info": temp[4] } );
	}

	// test for empty case (side effect of .split on an empty string is one "" returned)
	lastDataIndex = latData.length - 1;
	if ( lastDataIndex == 0 && latData[0] == "" ) {
		latData = Array();
		lonData = Array();
		ecodeData = Array();
		lastDataIndex = -1;
	}

	haveEcode = ( ecodeData.length < 2 ) ? false : true;

	setupIcons();

	adjustMapPosition();
	map = new GMap(document.getElementById('map'));
	map.addControl(new GLargeMapControl());
	map.addControl(new GMapTypeControl());
	//map.addControl(new GHierarchicalMapTypeControl());

	// 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);

	if ( document.forms[0].centerlon.value == '0' )
		map.centerAndZoom(new GPoint(-80, 30), 16); //37.4419), 16);	// World Map View!
	else
		map.centerAndZoom(new GPoint(eval(document.forms[0].centerlon.value),eval(document.forms[0].centerlat.value)), eval(document.forms[0].zoom.value));

	// load and draw line
	if ( pathEditable == true ) {
		//alert("loadDataToClickData");
		loadDataToClickData();
	}
	else
	{
		//alert("loadDataToReadOnlyDisplay");
		loadDataToReadOnlyDisplay();
		drawReadOnlyPath();
		drawPauseResumeMarkers();
		drawMileMarkers();
	}

	loadMarkerData();

	// manage the cursor
	document.getElementById('map').onmouseover = function() {
		if ( editMode == 'off' )
			document.getElementById('map').style.cursor = 'default';
		else
			document.getElementById('map').style.cursor = 'crosshair';
	}

	// setup the listener
	GEvent.addListener(map, 'click', function(marker, point) {
		handleClick(marker, point);
	} );

	setupEditButtons( document.forms[0].autoselectroute.value );

	// setup dirty flags
	if ( document.forms[0].markersdirty.value == '1' )
		setMarkersDirty( true );
	else
		setMarkersDirty( false );
	if ( document.forms[0].pathdirty.value == '1' )
		setPathDirty( true );
	else
		setPathDirty( false );

}

function drawClickPolylines()
{
	for (var i = 0; i < clickPolylines.length; i++)
		map.addOverlay( new GPolyline(clickPolylines[i], "#4000ff", 5, 0.6) );
}

function drawReadOnlyPath()
{
	for (var i = 0; i < pathArraySet.length; i++)
		map.addOverlay( new GPolyline(pathArraySet[i], "#4000ff", 5, 0.6) );
	if ( lastDataIndex > -1 ) {
		if ( lonData[lastDataIndex] == lonData[0] && latData[lastDataIndex] == latData[0] )
			map.addOverlay( new GMarker( new GPoint(parseFloat(lonData[0]),parseFloat(latData[0])),startendIcon) );
		else
		{
			map.addOverlay( new GMarker( new GPoint(parseFloat(lonData[lastDataIndex]),parseFloat(latData[lastDataIndex])),endIcon ) );
			map.addOverlay( new GMarker( new GPoint(parseFloat(lonData[0]),parseFloat(latData[0])),startIcon) );
		}
	}
}

function drawPauseResumeMarkers()
{
	for (var i = 0; i < pauseMarkerArray.length; i++)
		map.addOverlay( pauseMarkerArray[i] );
	for (var i = 0; i < resumeMarkerArray.length; i++)
		map.addOverlay( resumeMarkerArray[i] );
}

function drawMileMarkers()
{
	for (var i = 0; i < mileMarkers.length; i++)
	{
		map.addOverlay( mileMarkers[i] );
	}
}

function redrawMap( items )
{
	map.clearOverlays();
	drawOverlays();
}

function setPathDirty( isDirty )
{
//	alert("setPathDirty:"+isDirty);

	pathDirty = isDirty;
//	if ( pathDirty && shouldShowSave )
//		showSave();
	setPathDirtyLocal( isDirty );
}

function setPathDirtyLocal( isDirty )
{
//	alert("setPathDirtyLocal:"+isDirty);
	pathDirtyLocal = isDirty;
	if ( pathDirtyLocal && shouldShowSave )
		showSave( true );
}

function setMarkersDirty( isDirty )
{
	markersDirty = isDirty;
//	if ( markersDirty && shouldShowSave )
//		showSave();
	setMarkersDirtyLocal( isDirty );
}

function setMarkersDirtyLocal( isDirty )
{
	markersDirtyLocal = isDirty;
	if ( markersDirtyLocal && shouldShowSave )
		showSave( true );
}

function showSave( doShow)
{
	if ( doShow == true ) {
		document.getElementById('infobarbottom').style.display = '';
		document.getElementById('savebutton').style.display = '';
	} else {
		document.getElementById('infobarbottom').style.display = 'none';
		document.getElementById('savebutton').style.display = 'none';
	}
}

/*function clearPath()
{
	setPathDirty(true);
	clickData = Array();
	clickPolylines = Array();
	clickEndMarker = null;
	clickStartMarker = null;
	map.clearOverlays();
	updateExternalFormFields( 0 );
}*/

// add a point and line segment to the editable map line
function addPathPoint( lon, lat, shouldCenter )
{
	setPathDirty(true);
	lon = parseFloat(lon);
	lat = parseFloat(lat);

	var dataLen = clickData.length;

	// calc cum distance
	var dist = 0.0;
	var cumdist = 0.0;
	if ( dataLen > 0 ) {
		dist = calcDist(clickData[dataLen-1]["lon"],clickData[dataLen-1]["lat"],lon,lat);
		cumdist = clickData[dataLen-1]["cumdist"] + dist;
	}

	clickData.push( {"lon":lon, "lat":lat, "dist":dist, "cumdist":cumdist } );
	dataLen++;

	if ( dataLen > 1 )  {
		clickPolylines.push( new GPolyline( new Array(	new GPoint(clickData[dataLen-2]["lon"],clickData[dataLen-2]["lat"]),
										new GPoint(lon,lat) ), "#4000ff", 5, 0.6)  );
		if ( clickEndMarker )
			map.removeOverlay( clickEndMarker );
		map.addOverlay( clickPolylines[clickPolylines.length - 1] );

		// if we're back at start, use the special start/end Marker
		if ( clickData[0]["lon"] == clickData[dataLen-1]["lon"] && clickData[0]["lat"] == clickData[dataLen-1]["lat"] )
			clickEndMarker = new GMarker( new GPoint(lon,lat),startendIcon );
		else
			clickEndMarker = new GMarker( new GPoint(lon,lat),endIcon );

		map.addOverlay( clickEndMarker );
	}
	else if ( dataLen > 0 ) {
		clickStartMarker = new GMarker( new GPoint(clickData[0]["lon"],clickData[0]["lat"]),startIcon );
		map.addOverlay( clickStartMarker );
	}

	if ( shouldCenter )
		map.recenterOrPanToLatLng( new GPoint(lon,lat) );
	updateExternalFormFields( cumdist );
}

// remove the last segment from the editable line
function killLastPathSegment()
{
	setPathDirty(true);
	map.removeOverlay( clickEndMarker );
	map.removeOverlay( clickPolylines[clickPolylines.length - 1] );
	clickData.pop();
	clickPolylines.pop();
	var dataLen = clickData.length;
	if ( dataLen > 1 ) {
		clickEndMarker = new GMarker( new GPoint(clickData[dataLen-1]["lon"],clickData[dataLen-1]["lat"]),endIcon );
		map.addOverlay( clickEndMarker );
	} else if ( dataLen == 0 )
			map.removeOverlay( clickStartMarker );

	map.recenterOrPanToLatLng( new GPoint(clickData[dataLen-1]["lon"],clickData[dataLen-1]["lat"]) );
	updateExternalFormFields( (dataLen == 0) ? 0 : clickData[dataLen-1]["cumdist"] );
}

// extend the editable line...mirrored back over the existing points...returning to start
function backTrackPath()
{
	// follow the outbound point set back to the start
	var dataLen = clickData.length;
	if ( dataLen > 1 && !(clickData[0]["lon"] == clickData[dataLen-1]["lon"] && clickData[0]["lat"] == clickData[dataLen-1]["lat"]) )
		for (var i = dataLen-2; i >= 0; i--)
			addPathPoint( clickData[i]["lon"],clickData[i]["lat"], true );
}

// jump back to the path start location (straight line, it's now the next point)
function backToPathStart()
{
	// close the path by adding one more point that is the start location
	var dataLen = clickData.length;
	if ( dataLen > 1 && !(clickData[0]["lon"] == clickData[dataLen-1]["lon"] && clickData[0]["lat"] == clickData[dataLen-1]["lat"]) )
		addPathPoint( clickData[0]["lon"],clickData[0]["lat"], true );
}

// add a point of interest
function addMarker( markerType, lon, lat, label, info, addToData)
{
	if ( addToData ) setMarkersDirty(true);
	var icon = startIcon;

	if ( markerType == "water" ) {
		label = "Water";
		icon = waterIcon;
	} else if ( markerType == "food" ) {
		label = "Food";
		icon = foodIcon;
	} else if ( markerType == "view" ) {
		label = "View";
		icon = viewIcon;
	} else if ( markerType == "bathroom" ) {
		label = "Bathroom";
		icon = bathroomIcon;
	} else if ( markerType == "parking" ) {
		label = "Parking";
		icon = parkingIcon;
	} else if ( markerType == "other" ) {
		label = "Other";
		icon = otherIcon;
	}

	if ( addToData == true )
		markerData.push( {"type":markerType, "lon":lon, "lat":lat, "label":label, "info":""} );
	amarker = new GMarker(new GPoint(lon,lat),icon );
//	GEvent.addListener(amarker, 'click',
//		function(overlay) { markerClickHandler(overlay); } );

	map.addOverlay( amarker );
}

// marker click handler - called from the marker event listener
function markerClickHandler( overlay )
{
	if ( editMode != "off" && editMode != "line" ) {
		map.removeOverlay(overlay);
		for (var i = 0; i < markerData.length; i++ )
			if ( markerData[i]["lon"] == overlay.point.x && markerData[i]["lat"] == overlay.point.y )
			{
				markerData.splice(i, 1);
				setMarkersDirty(true);
				break;
			}
	}
}

// modify edit mode
function setEditMode( themode )
{
	editMode = themode;
	setIconHilite( themode, false );
	setInfoMessage( themode, false );
}

// this function is the same distance formula used in the php code and handset code
function calcDist(lon1,lat1,lon2,lat2)
{
	var fDegreesToRadians = 3.1415926535897932 / 180.0;	// pi / 180.0
	// Used in distance calculations: <earth radius> * degreesToRadians factor
	var fLatLonDistPrecalc = 3963.1676 * fDegreesToRadians;

	/* Pseudo code to calculate the distance between two (lat,lon) points
	var earthRadiusInMiles:Number = 3963.1676;
	var degreesToRadians:Number = Math.PI / 180.0;

	var longDiff:Number = begin.getLongitude() - end.getLongitude();
	var latDiff:Number = begin.getLatitude() - end.getLatitude();

	var latitudeOfInterest:Number = begin.getLatitude() * degreesToRadians;

	var xProjection:Number = earthRadiusInMiles * degreesToRadians * longDiff * Math.cos(latitudeOfInterest);
	var yProjection:Number = earthRadiusInMiles * degreesToRadians * latDiff;

	var xProjectionSquare:Number = xProjection * xProjection;
	var yProjectionSquare:Number = yProjection * yProjection;

	var xyDistance = Math.sqrt(xProjectionSquare + yProjectionSquare);
	*/

	// Lat & Lon differences
	var	lonDiff = lon1 - lon2;
	var	latDiff = lat1 - lat2;

	// X & Y projections
	var	xProjection = fLatLonDistPrecalc * lonDiff * Math.cos(lat1 * fDegreesToRadians);
	var	yProjection = fLatLonDistPrecalc * latDiff;

	// Xproj ^ 2 and Yproj ^ 2
	var	xProjectionSquare = xProjection * xProjection;
	var	yProjectionSquare = yProjection * yProjection;

	//##
	// echo sprintf("lonDiff = %.10f, preCalc = %.10f, xProjection = %.10f, yProjection = %.10f, xProjectionSquare = %.10f, yProjectionSquare = %.10f, cos = %.10f<br>", $lonDiff, $this->fLatLonDistPrecalc, $xProjection, $yProjection, $xProjectionSquare, $yProjectionSquare, cos($lat1 * $this->fDegreesToRadians));
	// echo sprintf("lon1 = %.15f, lon2 = %.15f, lonDiff = %.15f, preCalc = %.15f cos = %.15f<br>", $lon1, $lon2, $lonDiff, $this->fLatLonDistPrecalc, cos($lat1 * $this->fDegreesToRadians));

	// Sqrt(sum of squares)
	var	xyDistance = Math.sqrt( xProjectionSquare + yProjectionSquare );

	return xyDistance;

// this function is from www.geocoder.us and was used previous to 10/12/2007
/*
   var r = 3963.0;
   var multiplier = 1;
   return multiplier * r * Math.acos(Math.sin(lat1/57.2958) *
           Math.sin(lat2/57.2958) +  Math.cos(lat1/57.2958) *
           Math.cos(lat2/57.2958) * Math.cos(lon2/57.2958 -
           lon1/57.2958));
*/
}

// returns a shorted float representation.  second param is places "past decimal point"
function formatFloat(pFloat, pDp){
    var m = Math.pow(10, pDp);
    return parseInt(Math.round(pFloat * m), 10) / m;
}

// load markers
function loadMarkerData()
{
	for ( var i = 0; i < markerData.length; i++ )
	{
		addMarker( markerData[i]["type"], markerData[i]["lon"], markerData[i]["lat"], markerData[i]["label"], markerData[i]["info"], false);
	}
	//setMarkersDirty(false);
}

// load existing form data into an editable line (and display)
function loadDataToClickData()
{
	for ( var i = 0; i < lonData.length; i++ )
		if ( !haveEcode || ecodeData[i] == "" ) addPathPoint( lonData[i],latData[i], false );
	//setPathDirty(false);
}

// load existing data into a read-only display mode (handle huge numbers of points, pauses, and lost signal
function loadDataToReadOnlyDisplay()
{
	// build the path array of GPoints
	pathArraySet = Array();			// set of any/all drawable GPolyline
	pauseMarkerArray = Array();		// pause marker set of GMarker
	resumeMarkerArray = Array();	// resume marker set of GMarker
	var pathArray = Array();			// single GPolyline
	var lastLatLonIndex = 0;
	var addResumeMarkerNeeded = false;
	var lostGPS = false;
	for (var i = 0; i <= lastDataIndex; i++) {
		if ( !haveEcode || ecodeData[i] == "" ) {
			if ( lostGPS == true ) {
				// start a new line segment because we are back from lost GPS
				pathArraySet.push(pathArray);
				pathArray = Array();
				continue;
			}
			pathArray.push( new GPoint(lonData[i],latData[i]) );
			lastLatLonIndex = i;
			if ( addResumeMarkerNeeded == true ) {
				resumeMarkerArray.push( new GMarker(new GPoint(lonData[lastLatLonIndex],latData[lastLatLonIndex]),resumeIcon ) );
				addResumeMarkerNeeded = false;
			}
			if ( pathArray.length > 100 ) {  // keep line segments under 100 points each
				pathArraySet.push(pathArray);
				pathArray = Array();
				pathArray.push( new GPoint(lonData[i],latData[i]) ); // make sure segments are connected!
			}
		}
		else if ( haveEcode && ecodeData[i] == "100" ){
			pauseMarkerArray.push( new GMarker(new GPoint(lonData[lastLatLonIndex],latData[lastLatLonIndex]),pauseIcon ) );
		}
		else if ( haveEcode && ecodeData[i] == "101" ) {
			// start a new line segment
			addResumeMarkerNeeded = true;
			pathArraySet.push(pathArray);
			pathArray = Array();
		}
		else if ( haveEcode && ecodeData[i] == "127" ) {
			// Invalid fix status code, just skip point
		}
		else { // out of GPS coverage
			lostGPS = true;
		}
	}
	if ( pathArray.length > 0 ) {
		pathArraySet.push(pathArray);
		pathArray = null;
	}
	
	// Calc the position of mile markers for the path
	var		cumDist = 0.0;
	var		deltaMiles = 0.0;
	var		units = document.forms[0].readonlyunits.value;
	var		totalDistance = document.forms[0].readonlytotaldist.value;	// In English or Metric units
	
	// Determine at what interval to lay down the markers based upon the total distance. Note, we never
	// want more than about 50 markers for performance reasons
	var		markerInterval = totalDistance / 50.0;
	
	if (markerInterval < 1.0)
	{
		markerInterval = 1.0;
	}
	else
	if (markerInterval < 2.0)
	{
		markerInterval = 2.0;
	}
	else
	if (markerInterval < 5.0)
	{
		markerInterval = 5.0;
	}
	else
	if (markerInterval < 10.0)
	{
		markerInterval = 10.0;
	}
	else
	if (markerInterval < 20.0)
	{
		markerInterval = 20.0;
	}
	else
	if (markerInterval < 50.0)
	{
		markerInterval = 50.0;
	}
	else
	if (markerInterval < 100.0)
	{
		markerInterval = 100.0;
	}
	else
	if (markerInterval < 200.0)
	{
		markerInterval = 200.0;
	}
	else
	if (markerInterval < 500.0)
	{
		markerInterval = 500.0;
	}
	else
	if (markerInterval < 1000.0)
	{
		markerInterval = 1000.0;
	}
	else
	if (markerInterval < 2000.0)
	{
		markerInterval = 2000.0;
	}
	else
	{
		markerInterval = 5000.0;
	}
	
	deltaMiles = markerInterval;
	if (units == 2)		// Convert kilometers to miles
	{
		deltaMiles = deltaMiles / 1.609344;		// 1.609344 = miles to kilometers conversion factor
	}
	
	var		nextMarker = deltaMiles;
	
	for (var i = 0; i < pathArraySet.length; i++)
	{
		var	nextArray = pathArraySet[i];
		
		for (var j = 0; j < (nextArray.length - 1); j++)
		{
			var	pt1 = nextArray[j];
			var	pt2 = nextArray[j + 1];
			
			// Calc distance between last two points (in miles)
			var	segDist = calcDist(pt1.x, pt1.y, pt2.x, pt2.y);			
			var	neededDist = nextMarker - cumDist;

			cumDist += segDist;
			
			// Have we reached the next marker? (this dist segment may have shot us past multiple markers, so loop)
			while (cumDist >= nextMarker)
			{
				// There's a good chance we've overshot the next marker, so linear
				// interpolate to the point where the next marker is exactly reached.
				// latInterp = lat1 + (neededDist * ((lat2-lat1)/distSeg))
				// lonInterp = lon1 + (neededDist * ((lon2-lon1)/distSeg))
				var	latLonPt = new GLatLng(pt1.y - (neededDist * ((pt1.y - pt2.y) / segDist)), pt1.x - (neededDist * ((pt1.x - pt2.x) / segDist)));
				
				// Add another mile marker
				if (units == 1)
				{
					mileMarkers.push( makeMileMarker(latLonPt, Math.floor(nextMarker)) );
				}
				else
				{
					mileMarkers.push( makeMileMarker(latLonPt, Math.floor(nextMarker * 1.609344)) );
				}

				// Set up for next marker
				nextMarker += deltaMiles;
				neededDist += deltaMiles;
			}
		}
	}
}

function saveChanges()
{
	mapWriteToForm();
	document.forms[0].submit();
	return false;
}

function mapWriteToForm()
{
	//alert("mapWriteToForm");
	if ( pathDirty == true || pathDirtyLocal == true ) {
			//alert("mapWritetoForm: about to WriteMapPath");
			writeMapPath();
	}
	else {
		document.forms[0].lat_vals.value = "";
		document.forms[0].lon_vals.value = "";
		document.forms[0].ecode_vals.value = "";
		document.forms[0].ts_vals.value = "";
		//alert("mapWriteToForm: Cleared form path slots");
	}

	if ( markersDirty == true)
			writeMarkers();
	else
		document.forms[0].markers.value = "";

	var center = map.getCenterLatLng();
	document.forms[0].centerlon.value = center.x;
	document.forms[0].centerlat.value = center.y;
	document.forms[0].zoom.value = map.getZoomLevel();

	var currentMapType = map.getCurrentMapType();
	if ( currentMapType == G_NORMAL_MAP  )
		document.forms[0].maptype.value = 'G_NORMAL_MAP';
	else if ( currentMapType == G_HYBRID_MAP  )
		document.forms[0].maptype.value = 'G_HYBRID_MAP';
	else if ( currentMapType == G_PHYSICAL_MAP )
		document.forms[0].maptype.value = 'G_PHYSICAL_MAP';
	else if ( currentMapType == G_SATELLITE_MAP  )
		document.forms[0].maptype.value = 'G_SATELLITE_MAP';
	else
		document.forms[0].maptype.value = 'BIM_TOPO';
}

// write path data back to the form
function writeMapPath()
{
	var lonString = "";
	var latString = "";
	for (var i = 0; i < clickData.length; i++ ) {
		lonString = lonString+clickData[i]["lon"]+",";
		latString = latString+clickData[i]["lat"]+",";
	}
	document.forms[0].lon_vals.value = (lonString.length != 0 ) ? lonString.substring(0,lonString.length-1) : "";
	document.forms[0].lat_vals.value = (latString.length != 0 ) ? latString.substring(0,latString.length-1) : "";
	document.forms[0].pathdirty.value = "1";
	//alert("wrote path to form");
}

// write marker data back to the form
function writeMarkers()
{
	var markerString = "";
	for (var i = 0; i < markerData.length; i++ ) {
		markerString = markerString+markerData[i]["type"]+","+markerData[i]["lon"]+","+markerData[i]["lat"]+","+markerData[i]["label"]+","+markerData[i]["info"]+";";
	}
	document.forms[0].markers.value = markerString;
	document.forms[0].markersdirty.value = "1";
}

// write updated 'stats' to form display fields on the page
function updateExternalFormFields( cumdist )
{
	//alert("distUnitsField: "+distUnitsField+"\nformDistField: "+formDistField);
	if ( formDistField != 'none' )
	{
		var distSpan = document.getElementById(formDistField);
		if ( distSpan != null && formDistField != 'none' ) {
			if ( distUnitsField != 'none' && document.getElementById(distUnitsField).selectedIndex == 1 )
				cumdist = cumdist * 1.6093;
			document.getElementById(formDistField).innerHTML = formatFloat( cumdist, 2 );
		}
	}
}

function handleClick(marker, point)
{

	if ( editMode == 'off' )
		return;

	if ( editMode == 'line' )
		addPathPoint(point.x, point.y, true);

	else // adding or removing a marker
	{
		if ( marker )
			removeMarker( marker );
		else
			addMarker( editMode, point.x, point.y, "", "", true);
	}

}

function removeMarker(marker)
{
	var markerPoint = marker.getPoint();
	map.removeOverlay(marker);
	for (var i = 0; i < markerData.length; i++ )
		if ( markerData[i]["lon"] == markerPoint.x && markerData[i]["lat"] == markerPoint.y )
		{
			markerData.splice(i, 1);
			setMarkersDirty(true);
			break;
		}
}


// Creates a mile marker icon
function makeMileMarker(point, mileNum)
{
	var newMMarkerIcon = new GIcon();
	
	if (mileNum < 10)
	{
		newMMarkerIcon.iconSize = new GSize(15, 15);
		newMMarkerIcon.iconAnchor = new GPoint(7, 7);
	}
	else
	if (mileNum < 100)
	{
		newMMarkerIcon.iconSize = new GSize(17, 15);
		newMMarkerIcon.iconAnchor = new GPoint(8, 8);
	}
	else
	if (mileNum < 1000)
	{
		newMMarkerIcon.iconSize = new GSize(23, 15);
		newMMarkerIcon.iconAnchor = new GPoint(11, 8);
	}
	else
	{
		newMMarkerIcon.iconSize = new GSize(28, 15);
		newMMarkerIcon.iconAnchor = new GPoint(14, 8);
	}
	
    newMMarkerIcon.image = "http://" + document.domain + "/ba/lib/images/mmarkers/mmarker_"+mileNum+".png";
	return new GMarker(point, newMMarkerIcon);
}

