var map; 
var label = new Array(0);
var uid = "";
var debug;
var bDoubleClickHappened = false;
var alt = false;
var shift = false;
var ctrl = false;
var xArray = new Array(0);
var yArray = new Array(0);
var zArray = new Array(0);
var locationArray = new Array(0);
var legArray = new Array(0);
var distancesArray = new Array(0);
var latLngArray = new Array(0);
var gLatLngArray = new Array(0);
var tempGLatLngArray = new Array(0);
var markerArray = new Array(0);
var markerHtmlArray = new Array(0);
var gMarkerArray = new Array(0);
var gMarkerPointArray = new Array(0);
var gMarkerLatLngArray = new Array(0);
var cue = new Array(0);
var cueDist = new Array(0);
var cueInfo = new Array(0);
var markerNum = 0;
var routePolyline
var distance = 0;
var bRecordPoints = false;
var REMOVE = 0;
var ADD = 1;
var MILES = "0";
var KILOMETERS = "1";
var selectCity = "";
var selectState = "";
var selectType = ""
var selectNewest = "";
var selectUid = "";
var currentFile = "";
var currentRouteId;
var currentRouteName;
var buildList = true;
var ZOOMAREA_KEYCODE = 90; //  z

CustomGetTileUrl=function(a,b,c) {
	var lULP = new GPoint(a.x*256,(a.y+1)*256);
	var lLRP = new GPoint((a.x+1)*256,a.y*256);
	var lUL = G_NORMAL_MAP.getProjection().fromPixelToLatLng(lULP,b,c);
	var lLR = G_NORMAL_MAP.getProjection().fromPixelToLatLng(lLRP,b,c);
	var lBbox=lUL.x+","+lUL.y+","+lLR.x+","+lLR.y;
	var lSRS="EPSG:4326";
	var lURL=this.myBaseURL;
	lURL+="&REQUEST=GetMap";
	lURL+="&SERVICE=WMS";
	lURL+="&reaspect=false&VERSION=1.1.1";
	lURL+="&LAYERS="+this.myLayers;
	lURL+="&STYLES=default";
	lURL+="&FORMAT="+this.myFormat;
	lURL+="&BGCOLOR=0xFFFFFF";
	lURL+="&TRANSPARENT=TRUE";
	lURL+="&SRS="+lSRS;
	lURL+="&BBOX="+lBbox;
	lURL+="&WIDTH=256";
	lURL+="&HEIGHT=256";
	lURL+="&GroupName="+this.myLayers;
	return lURL;
}


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 topoLayer=[tileDRG];
var topoMap = new GMapType(topoLayer, G_SATELLITE_MAP.getProjection(), "Topo", G_SATELLITE_MAP);



distancesArray.push(0);

function dbg(text) {
	if(debug=='1')GLog.writeHtml(text);
}

/*  Called when initial page is loaded
 *	and every time it is reloaded
 */
function initializeMap(){
	debug = getQuerystringParameter('xyzzy');
	if(debug=='1'){
		dbg("Debugging output<hr>"+debug);
	}
	var mapSpecs = new Array();
	mapSpecs.push(G_NORMAL_MAP);
	mapSpecs.push(G_SATELLITE_MAP);
	mapSpecs.push(G_HYBRID_MAP);
	mapSpecs.push(topoMap);

//intialize the map
	myMap = document.getElementById('map');
	map = new GMap2(myMap,{ mapTypes: mapSpecs });

	map.setCenter(new GLatLng(38.6385,-90.4495),4);
	map.addControl(new GScaleControl()); 
	map.setMapType(map.getMapTypes()[0]); 
	map.addControl(new GLargeMapControl());
	map.addControl(new GMapTypeControl());
	
	dbg("map and controls added");
	

	// init the zoom stuff
	initCoords();


	// add my logo
	var myLogo=document.createElement('div');
	myLogo.id='2WT';
	document.getElementById("map").appendChild(myLogo);
	mL = document.getElementById("2WT")
	mL.innerHTML='<a target="_blank" href="http://2wheeltech.com"><img src="/images/logo_2wheeltech60x20a.jpg" alt=""></a>';
	mL.style.position='absolute';
	mL.style.left='2px';
	mL.style.bottom='32px';
	mL.style.zIndex=1000;
	var c=0.7;
	var d=document.getElementById(mL.id);
	if(typeof(d.style.filter)=='string'){d.style.filter='alpha(opacity:'+c*100+')';}
	if(typeof(d.style.KHTMLOpacity)=='string'){d.style.KHTMLOpacity=c;}
	if(typeof(d.style.MozOpacity)=='string'){d.style.MozOpacity=c;}
	if(typeof(d.style.opacity)=='string'){d.style.opacity=c;}
	dbg("logo added");
	
	document.getElementById("newRoutePanel").style.display = "none";
	document.getElementById("routeQueryPanel").style.display = "none";
	document.getElementById("gpxPanel").style.display = "none";
	document.getElementById("routeListDiv").style.display = "none";
	document.getElementById("homePanel").style.display = "none";
	dbg("left panels added");

	buildList = true;
	getUid();

// Monitor the window resize event and let the map know when it occurs
// it is required to accomplish
// a correct full-screen Google Map????
	if (window.attachEvent) { 
	  window.attachEvent("onresize", function() { map.checkResize() } ); 
	} 
	else { 
	  window.addEventListener("resize", function() { map.checkResize() } , false);
	} 	

// set up the zoom function
	GEvent.addListener(map, "zoom", function() {   
		//zoom  or moveend
		var zoomLevel = map.getZoomLevel();
		if (zoomLevel > 15){
			map.zoomTo(15);
		}
	});

	
	
	GEvent.addListener(map, "click", function(overlay,point){
		if(overlay){
		}
		else if(point){
			document.newRoute.curLat.value = point.lng();
			document.newRoute.curLon.value = point.lat();
			getAltitude(point);
			// determine distance from route to this point
			routeDistToPoint(point.x,point.y);
		}
	});        

	GEvent.addListener(map, "dblclick", function(n,point) {
		dbg("DBL click");
// create marker
		if(ctrl || alt){
			dbg("Ctrl / Alt");
			addMarker(map.getCenter.lng(), map.getCenter.lat(), document.newRoute.markerText.value);
			document.newRoute.markerText.value = "";
			drawPolyLine(gLatLngArray,gMarkerArray);
		}
// create point
		else{
			curLatLng = point; 
			dbg("Point created<br>"+curLatLng.lat()+","+curLatLng.lng());
			addLeg(curLatLng.lng(), curLatLng.lat());
			drawPolyLine(gLatLngArray,gMarkerArray);
    }

//		bDoubleClickHappened = false;
//		alt = false;
//		ctrl=false;
//		shift=false;
	});

	home();
	dbg("Return from home()");
//	document.onkeydown = keyDownHandler;
	document.onKeyDown = alertkey;
 	var routeId = getQuerystringParameter('routeId');
 	if(routeId.length>0 & routeId!="0") {
		dbg('Call line2.php?routeId='+routeId);
 		document.getElementById('altProfile').src='line2.php?routeId='+routeId;
		doGet(routeId);	
 	}
}


//now create the event handler function to process the event
function alertkey(e) {
  dbg("alertkey");
	if( !e ) {
    //if the browser did not pass the event information to the
    //function, we will have to obtain it from the event register
    if( window.event ) {
      //Internet Explorer
      e = window.event;
    } else {
      //total failure, we have no way of referencing the event
			dbg("err");
      return;
    }
  }
  if( typeof( e.keyCode ) == 'number'  ) {
    //DOM
    e = e.keyCode;
  } else if( typeof( e.which ) == 'number' ) {
    //NS 4 compatible
    e = e.which;
  } else if( typeof( e.charCode ) == 'number'  ) {
    //also NS 6+, Mozilla 0.9+
    e = e.charCode;
  } else {
    //total failure, we have no way of obtaining the key code
    return;
  }
  window.alert('The key pressed has keycode ' + e +
    ' and is key ' + String.fromCharCode( e ) );
}	
	
/*	
	
	
	
	
function keyDownHandler(e){
	if (!e) var e = window.event;
	alt = (e.altKey) ? true : false;
	ctrl = (e.ctrlKey) ? true : false;
	shift = (e.shiftKey) ? true : false;
	dbg("keyDown<br>alt:"+alt+" ctrl:"+ctrl+" shift:"+shift+" keyCode:"+e.keyCode);
/*
	if ((startTracking == false) && (e.shiftKey) && (e.keyCode == ZOOMAREA_KEYCODE)){
		zoomx1 = mousex;
		zoomy1 = mousey;
		dbg("keyDown<br>alt:"+alt+" ctrl:"+ctrl+" shift:"+shift+" keyCode:"+e.keyCode+" startTracking:"+startTracking+ 	
			"<br>zx1,zy1:"+zoomx1+","+zoomy1+"xInB,y:"+xInBounds(zoomx1)+" "+yInBounds(zoomy1));
		if ((xInBounds(zoomx1)) && (yInBounds(zoomy1))) {
			startTracking = true;
			gpstart = getLatLonFromPixel(zoomx1 - mapx1, zoomy1 - mapy1); 
			zoomLayer.style.visibility = "visible";
			zoomLayer.style.left = zoomx1+"px";
			zoomLayer.style.top = zoomy1+"px";
			zoomLayer.style.width = 0+"px";
			zoomLayer.style.height = 0+"px";
			document.body.style.cursor = "crosshair";
		}
	}

}

function keyUpHandler(e){
	if (!e) e = window.event;
	alt = (e.altKey) ? true : false;
	ctrl = (e.ctrlKey) ? true : false;
	shift = (e.shiftKey) ? true : false;
	dbg("keyDown<br>alt:"+alt+" ctrl:"+ctrl+" shift:"+shift+" keyCode:"+e.keyCode);

	startTracking = false;
	if (!e) e = window.event;
	dbg("<br>keyUp<br>alt:"+alt+" ctrl:"+ctrl+" shift:"+shift+
		" keyCode:"+e.keyCode+" startTracking:"+startTracking);
	if (e.keyCode != ZOOMAREA_KEYCODE)
		return;
	if(typeof(gpstart) == 'undefined')
		return;
	zoomLayer.style.visibility = "hidden";
	document.body.style.cursor = "default";
	zoomx2 = mousex;
	zoomy2 = mousey;
	gpend = getLatLonFromPixel(mousex - mapx1, mousey - mapy1); 
	zoomarea = Math.abs((gpend.x - gpstart.x) * (gpend.y - gpstart.y));
	if (zoomarea == 0)
		return;
	var bounds = new GBounds(Number.MAX_VALUE, Number.MAX_VALUE, -Number.MAX_VALUE, -Number.MAX_VALUE); 
	bounds.extend(gpstart); 
	bounds.extend(gpend);
	map.centerAndZoomOnBounds(bounds); 		
//	map.centerAndZoom(new GPoint(centerx, centery), zoomLevel);

}
	
*/	





function home(){
	document.getElementById("newRoutePanel").style.display = "none";
	document.getElementById("routeQueryPanel").style.display = "none";
	document.getElementById("gpxPanel").style.display = "none";
	document.getElementById("routeListDiv").style.display = "none";
	document.getElementById("homePanel").style.display = "block";
	document.getElementById("altDiv").style.display = "none";
}
function panelDisplay(panel,display){
	if(panel.length>0){
  	for(i=0;i<panel.length-1;i++){
  		document.getElementById(panel[i]).style.display = display[i];
  	}
	}
}
/*
 * Print the map, currently doesnt print route
 */
function printMap(){
	document.getElementById("leftCol").style.display = 'none';
	document.getElementById("dbgmsg").style.display = 'none';
	document.getElementById("msg").style.display = 'none';
	document.getElementById("printDone").style.display = 'block';
	document.getElementById("mapPane").style.left = '0';
	document.getElementById("mapPane").style.width = '100%';
	document.getElementById("mapPane").style.height = '100%';
	document.getElementById("mapPane").style.position = 'absolute';
	window.print();
}
function printDone(){
	document.getElementById("printDone").style.display = 'none';
	document.getElementById("leftCol").style.display = 'block';
	document.getElementById("msg").style.display = 'block';
	document.getElementById("mapPane").style.left = '30%';
	document.getElementById("mapPane").style.width = '70%';
	document.getElementById("mapPane").style.height = '80%';
	document.getElementById("mapPane").style.position = 'absolute';
}



function routeDistToPoint(x,y){
	var minDist = 1000;
	var minI = 0;
	for(i=0; i<gLatLngArray.length-1; i++){
		ptDist = returnDistanceInMiles(y, x, gLatLngArray[i].y, gLatLngArray[i].x);
		if(ptDist<minDist){
			minDist = ptDist;
			minI = i;
		}
	}
	routeDist = returnDistanceInChosenUnits(distancesArray[minI]).toFixed(2);
	dbg("<b>routeDistToPoint</b> Closest pt:"+minI+":"+minDist+" Distance:"+routeDist+"mi.");
	return routeDist;
}



function getUid(){
  	uid = getQuerystringParameter('uid');
  	if(uid.length==0 || uid=="0"){
  		uid = 'public';
  	}
}


function getRouteList(p1,p2){
	var selectType = document.searchForm.rtype.value;
	var selectState= document.searchForm.state.value;
	var selectNewest = document.searchForm.newestRoutes.checked;
	var selectUid = uid;
	var display = new Array(0);
	var panel = new Array(0)		
	panel 	= ["newRoutePanel","routeQueryPanel","gpxPanel","routeListDiv","homePanel"];
	display = ["none",         "block",          "none",    "none",        "none",     "none"];

	buildList = true;
	if(arguments.length==1){
		if(p1==1) {
			document.searchForm.newestRoutes.checked = false;
			selectNewest = 1;
		}
		document.searchForm.rtype.value = 0;
		document.searchForm.state.value = 0;
		selectType = document.searchForm.rtype.value;
		selectState= document.searchForm.state.value;
		
	}
	else if(arguments.length>1){
		buildList = p2;
	}
	if(selectNewest==true)selectNewest=1;
	
	dbg("getRouteList<br>buildList="+buildList+" <br>selectType="+selectType+" <br>selectState="+selectState+
		" <br>selectNewest="+selectNewest+" <br>selectUid="+selectUid);
	
	if(!buildList || buildList=="false"){
		display = ["none","block","none","none","none","none"];
		
		panelDisplay(panel, display);
		buildList = true;
		return;
	}
	else{
		display = ["none", "none", "none", "block", "none", "none"];
		panelDisplay(panel, display);

		var selectNone = false;
//		buildList = false;
	}

	if(selectNone) {
		var routeId= new Array(0);
		routeId[0] = "";
		clearCurrentRoute();
		map.centerAndZoom(new GPoint(-90.4495, 38.6385), 13);

		return;
	}

	args ="";
	if(selectState!="" && selectState!=0) args += "&state="+selectState;
	if(selectType!="") args += "&type="+selectType;
	if(selectNewest!="") args += "&newest="+selectNewest;
	if(selectUid!="") args += "&selectUid="+selectUid;
	if(args != "") args = "?"+args;
	dbg('getRouteList'+args);
	request = GXmlHttp.create();
	request.open("GET", "getRouteList.php"+args, true);
	
	request.onreadystatechange = function() {
		dbg('getRouteList readyState: '+request.readyState);
		if (request.readyState == 4) {
			var xmlDoc = request.responseXML; 
			var nodes = xmlDoc.getElementsByTagName("route");	
			dbg('Nodes retrieved: ' + nodes.length);			
			var routeListDiv = document.getElementById("routeListDiv");
			dbg("define routeListDiv");
			if(nodes.length==0){
				routeListDiv.innerHTML = "No routes meet this criteria";
			}
			else{
				if(document.getElementById("newTable")){
					document.getElementById("routeListDiv").removeChild(document.getElementById("newTable"));
				}
				var newTable = document.createElement('table');
	
				newTable.id = 'newTable';
				var newBody = document.createElement('tBody');
				newTable.appendChild(newBody);
				//create holders
				var r  = document.createElement('tr'); 
			  var cn = document.createElement('th'); // name
				cn.id = 'nameCol';
			  var ca = document.createElement('th'); // routeId
			  var cc = document.createElement('th'); // Dist
			  var cf = document.createElement('th'); // State
				cf.id = 'stateCol';
				//create contents
			  var tn = document.createTextNode('Name');
			  var ta = document.createTextNode('ID');
			  var tc = document.createTextNode('Dist');
			  var tf = document.createTextNode('State');
				//add contents to holders
				cn.appendChild(tn);
				ca.appendChild(ta);	
				cc.appendChild(tc);	
				cf.appendChild(tf);
				//add cells to row
				r.appendChild(cn);
				r.appendChild(ca);
				r.appendChild(cc);
				r.appendChild(cf);
				newBody.appendChild(r);
	
				dbg("Table header built");
				dbg(nodes.length+" nodes found"); 
	  		for ( var i = 0 ; i < nodes.length ; i ++ ) {
//	  			dbg("i= "+i);
	  			name = nodes[i].getAttribute("routeName");
					routeId = nodes[i].getAttribute("routeId");
					dist = 0.0;
					state = nodes[i].getAttribute("state");
					
					//create holders
					var r  = document.createElement('tr');
					if (i%2 == 1) {
						r.className = 'stripe';
					} 
					else {
						r.className = 'nostripe';
					}
//					dbg("Created Row holder "+r.className);
	
				  var cn = document.createElement('td'); // name
			    var ca = document.createElement('td'); // routeId
			    var cc = document.createElement('td'); // dist
			    var cf = document.createElement('td'); // state
	
					var ah = document.createElement('a');
					//ah.onclick='return doGet(\""+routeId+"\");';
					xuid = "";
					if(selectUid!="public") xuid = "&uid="+selectUid;
					var xyzzy = "";
					if(debug=='1')xyzzy = "&xyzzy";
					ah.href='javascript:document.getElementById("altProfile").src="line2.php?routeId='+routeId+'"; document.getElementById("newRoutePanel").style.display = "block"; document.getElementById("routeListDiv").style.display = "none"; doGet("'+routeId+'");';	//currentFile+"?routeId="+routeId+xuid+xyzzy;
	
					//create contents
			    var tn = document.createTextNode(name);
			    var ta = document.createTextNode(routeId);
			    var tc = document.createTextNode(dist);
			    var tf = document.createTextNode(state);
					
					//add contents to holders
					ah.appendChild(tn);
					cn.appendChild(ah);
					
					ca.appendChild(ta);	
					cc.appendChild(tc);	
					cf.appendChild(tf);
	
					//add cells to row
					r.appendChild(cn);
					r.appendChild(ca);
					r.appendChild(cc);
					r.appendChild(cf);
					newBody.appendChild(r);
					routeListDiv.appendChild(newTable);
	  		}
	  	}
 		}
	}
  request.send(null);
}

/*

function keyDownHandler(e){
	if (!e) var e = window.event;
	alt = (e.altKey) ? true : false;
	ctrl = (e.ctrlKey) ? true : false;
	shift = (e.shiftKey) ? true : false;
	if ((startTracking == false) && (e.shiftKey) && (e.keyCode == ZOOMAREA_KEYCODE)){
		zoomx1 = mousex;
		zoomy1 = mousey;
		dbg("keyDown<br>alt:"+alt+" ctrl:"+ctrl+" shift:"+shift+" keyCode:"+e.keyCode+" startTracking:"+startTracking+ 	
			"<br>zx1,zy1:"+zoomx1+","+zoomy1+"xInB,y:"+xInBounds(zoomx1)+" "+yInBounds(zoomy1));
		if ((xInBounds(zoomx1)) && (yInBounds(zoomy1))) {
			startTracking = true;
			gpstart = getLatLonFromPixel(zoomx1 - mapx1, zoomy1 - mapy1); 
			zoomLayer.style.visibility = "visible";
			zoomLayer.style.left = zoomx1+"px";
			zoomLayer.style.top = zoomy1+"px";
			zoomLayer.style.width = 0+"px";
			zoomLayer.style.height = 0+"px";
			document.body.style.cursor = "crosshair";
		}
	}
}

function keyUpHandler(e){
	startTracking = false;
	if (!e) e = window.event;
	dbg("<br>keyUp<br>alt:"+alt+" ctrl:"+ctrl+" shift:"+shift+
		" keyCode:"+e.keyCode+" startTracking:"+startTracking);
	if (e.keyCode != ZOOMAREA_KEYCODE)
		return;
	if(typeof(gpstart) == 'undefined')
		return;
	zoomLayer.style.visibility = "hidden";
	document.body.style.cursor = "default";
	zoomx2 = mousex;
	zoomy2 = mousey;
	gpend = getLatLonFromPixel(mousex - mapx1, mousey - mapy1); 
	zoomarea = Math.abs((gpend.x - gpstart.x) * (gpend.y - gpstart.y));
	if (zoomarea == 0)
		return;
	var bounds = new GBounds(Number.MAX_VALUE, Number.MAX_VALUE, -Number.MAX_VALUE, -Number.MAX_VALUE); 
	bounds.extend(gpstart); 
	bounds.extend(gpend);
	map.centerAndZoomOnBounds(bounds); 		
//	map.centerAndZoom(new GPoint(centerx, centery), zoomLevel);
}



function handleDblClick(e) {
	if (!e) var e = window.event;
	bDoubleClickHappened = true;
 	alt = (e.altKey) ? true : false;
	ctrl = (e.ctrlKey) ? true : false;
	shift = (e.shiftKey) ? true : false;
}
*/

function saveGpx(){
	saveAsGpx(gLatLngArray);
}

function saveAsGpx(gLatLngArray){
	var route=1;
	dbg("Create GPX from "+gLatLngArray.length+" points");
	var gpxOutput = document.getElementById("gpxOutput");
	gpxOutput.style.display = "block";
	var output = document.getElementById("output");
	output.value = "";
	if(gLatLngArray.length>0){
		output.value = make_gpx(currentRouteName,gLatLngArray,1);
	}
	else {
		output.value = "No route points available to create a gpx listing.\nMake sure you"+
		" have loaded a route before trying to save";
	}	
	dbg("gpx text<br>"+output.value);
	output.focus();
}


function doSave() {
	newRouteName = document.newRoute.newRouteName.value;
	city = document.newRoute.city.value;
	state = document.newRoute.state.value;
	newRouteType = document.newRoute.newType.selectedIndex;
	comments = document.newRoute.comments.value;
	email = document.newRoute.email.value;
	newRouteUid = uid;
	dist = document.controlPanel.mileage.value;
	if(newRouteName=='' || city=='' || state=='' || email==""){
		alert("You must enter a Route Name, City, State\nand Email address before you can save.\n Comments are optional");
		return;
	}
	dbg("<b>routeSave.php</b>");
	request = GXmlHttp.create();
	request.onreadystatechange = function() {
		dbg('routeSave readyState:'+request.readyState+'<br>'+
				'routeSave responseText:'+request.responseText);
		if (request.readyState == 4) {
			dbg('routeSave responseText:'+request.responseText);
			var xmlDoc = request.responseXML; 
 			var nodes = xmlDoc.getElementsByTagName("msg");	
			dbg('routeSave Nodes retrieved: ' + nodes.length);			
			for ( var i = 0 ; i < nodes.length ; i ++ ) {
				name = nodes[i].getAttribute("routeName");
				routeRC = nodes[i].getAttribute("routeRC");
				routeStatus = nodes[i].getAttribute("routeStatus");
				routeQuery = nodes[i].getAttribute("routeQuery")
				pointQuery = nodes[i].getAttribute("pointQuery")
				pointStatus = nodes[i].getAttribute("pointStatus")
				markerStatus = nodes[i].getAttribute("markerStatus")
				markerQuery = nodes[i].getAttribute("markerQuery")
				dmsg = '<b>routeSave.php</b> returned<br>' + name + "<br>RouteRC:"+routeRC+
					"<br>Route Status:"+routeStatus+"<br>Route Query:"+routeQuery+ 
					"<br>Point Status:"+pointStatus+"<br>Point Query:"+pointQuery+
					"<br>Marker Status:"+markerStatus+"<br>Marker Query:"+markerQuery;
				dbg(dmsg)
			}
			if(routeRC==1){
				alert("Route Name "+name+" already exists\nPlease enter a new name\nand Save again");
			}
			else if(routeRC==0){
				dbg("RouteSave: Status:"+routeStatus);
				mailer(dmsg,document.newRoute.email.value, name);
				getRouteList();
			}
			else{
				alert("Route Not saved,"+routeStatus);
			}
		}
	}
	data = "routeName="+newRouteName + "&numPoints="+gLatLngArray.length + 
		"&pointArray="+prepPointArray1(gLatLngArray) + 
		"&numMarkers="+gMarkerPointArray.length + 
		"&markerArray="+prepPointArray1(gMarkerPointArray) + 
		"&markerHtmlArray="+prepArray(markerHtmlArray) + 
		"&city="+city + 
		"&state="+state +
		"&routeTypeId="+newRouteType +
		"&routeUid="+newRouteUid + 
		"&dist="+dist +
		"&email="+email + 
		"&comments="+escape(comments);
  request.open("POST", "routeSave.php", true);
	dbg("Post Data for routeSave.php<br>"+data);
	header='Content-Type:application/x-www-form-urlencoded; charset=UTF-8'; 			
	request.setRequestHeader(header.split(':')[0],header.split(':')[1]);
	request.send(data);
}



function createCueSheet(){
	var routeId = currentRouteId;
	request = GXmlHttp.create();
	dbg('<b>createCueSheet</b> GET cueSheetGet.php?routeId='+routeId);
	request.open("GET", "cueSheetGet.php?routeId="+routeId, true);
	request.onreadystatechange = function(){
		dbg('cueSheetGet readyState'+request.readyState+'<br>'+
				'responseText:'+request.responseText);
  		if (request.readyState == 4) {
			dbg("Response from cueSheetGet Request<br>"+request.responseText);
			var xmlDoc = request.responseXML;
			// get all routes					 
			var cueNodes = xmlDoc.documentElement.getElementsByTagName("cue");	
			dbg(' Cues retrieved: ' + cueNodes.length);
			var cueInfo = new Array(0);
			var cueDist = new Array(0);
			for(var i=0; i<cueNodes.length; i++){
				cueInfo[i] = cueNodes[i].getAttribute("info");
//				cue[i].lat = cueNodes[i].getAttribute("lat");
//				cue[i].lon = cueNodes[i].getAttribute("lon");
				cueDist[i] = routeDistToPoint(cueNodes[i].getAttribute("lon"),cueNodes[i].getAttribute("lat"));
			}
			if(debug=="1"){
				dbg("cueDist before sort");
				for(x=0;x<cueDist.length;x++){
					dbg(cueDist[x]);
				}
			}
			bSort(cueDist,cueInfo);
			if(debug=="1"){
				dbg("cueDist after sort");
				for(x=0;x<cueDist.length;x++){
					dbg(cueDist[x]);
				}
				dbg("cueInfo len:"+cueInfo.length);
			}
			displayCueSheet(cueInfo,cueDist);
		}
	}
	request.send(null);
}

function bSort(ranarray, barray) {
  var x, y, holder;
  // The Bubble Sort method.
  for(x = 0; x < ranarray.length; x++) {
    for(y = 0; y < (ranarray.length-1); y++) {
      if(parseFloat(ranarray[y]) > parseFloat(ranarray[y+1])) {
        holder = ranarray[y+1];
        ranarray[y+1] = ranarray[y];
        ranarray[y] = holder;
        holder = barray[y+1];
        barray[y+1] = barray[y];
        barray[y] = holder;
      }
    }
  }
}

function displayCueSheet(cueInfo,cueDist){
	var dist;
	myWin= open("", "displayWindow", 
	    "width=500,height=400,status=yes,toolbar=no,menubar=no,scrollbars=yes");
	// open document for further output
	myWin.document.open();
	// create document
	myWin.document.write("<html><head><title>On-the-fly");
	myWin.document.write("</title></head><body>");
	myWin.document.write("<a href='javascript:print();'>Print Page</a>");
	if(cueInfo.length>0){
		myWin.document.write("<h3>"+currentRouteName+"</h3><table><tr><td>Next Cue</td><td>Info</td><td>Mile</td></tr>");
		myWin.document.write("<tr><td>0.0</td><td>"+cueInfo[0]+"</td><td>0.0</td</tr>");
		for(i=1; i<cueInfo.length; i++){
			dist = cueDist[i]-cueDist[i-1];
			myWin.document.write("<tr><td>"+dist.toFixed(1)+"</td><td>"+cueInfo[i]+"</td><td>"+cueDist[i]+"</td</tr>");
		}
		myWin.document.write("</table>");
		myWin.document.write("<a href='javascript:print();'>Print Page</a>");
	}
	else{
		myWin.document.write("No cue information has been added for <em>"+currentRouteName+"</em><br><br>This is a new "+
		"feature that is not ready "+
		"to be released.  Watch the release information at the bottom of the HELP to see when it is made available");
	}
	myWin.document.write("</body></html>");
	// close the document - (not the window!)
	myWin.document.close();  
}


function getGpx(){
		document.getElementById("newRoutePanel").style.display = "none";
		document.getElementById("routeQueryPanel").style.display = "none";
		document.getElementById("gpxPanel").style.display = "block";
		document.getElementById("routeListDiv").style.display = "none";
		document.getElementById("homePanel").style.display = "none";

}

function newGetGpx(){
		document.getElementById("newRoutePanel").style.display = "none";
		document.getElementById("routeQueryPanel").style.display = "none";
		document.getElementById("newGpxPanel").style.display = "block";
		document.getElementById("routeListDiv").style.display = "none";
		document.getElementById("homePanel").style.display = "none";

}
function traverse(tree) {
	if(tree.hasChildNodes()) {
		dbg('<ul><li>');
		dbg('<b>'+tree.tagName+' : </b>');
		var nodes=tree.childNodes.length;
		for(var i=0; i<tree.childNodes.length; i++)
			traverse(tree.childNodes[i]);
		dbg('</li></ul>');
	}
	else
		dbg(tree.text);
}
function doGet(routeId) {
	dbg('<b>doGet</b> GET routeGet.php?routeId='+routeId);
	request = GXmlHttp.create();
	request.open("GET", "routeGet.php?routeId="+routeId, true);
	request.onreadystatechange = function() {
		dbg('routeGet readyState'+request.readyState);
  		if (request.readyState == 4) {
			clearCurrentRoute();
//			dbg("Response from doGet Request<br>"+encodeURI(request.responseText));
			var xmlDoc = request.responseXML;
//			traverse(xmlDoc.documentElement);
			// get all routes					 
			var routeNodes = xmlDoc.documentElement.getElementsByTagName("route");	
			dbg(' Routes retrieved: ' + routeNodes.length);
			for ( var i = 0 ; i < routeNodes.length ; i++ ) {
				// get the name of this one
				routeName = routeNodes[i].getAttribute("routeName");
				routeId = routeNodes[i].getAttribute("routeId");
				routeCity = routeNodes[i].getAttribute("routeCity");
				routeState = routeNodes[i].getAttribute("routeState");
				routeTypeId = routeNodes[i].getAttribute("routeTypeId");
				routeComments = routeNodes[i].getAttribute("routeComments");
				dbg("Route "+routeName+" retrieved<br>Id:"+routeId+" City:"+
						routeCity+" State:"+routeState+" typeId:"+routeTypeId+" comments:"+routeComments);
				// get the markers for this route
				var markerNodes = routeNodes[i].getElementsByTagName("marker");
				dbg(" Marker types retrieved: " + markerNodes.length);
				for (var j = 0 ; j < markerNodes.length ; j++ ){
					var markerType = markerNodes[j].getAttribute("type");
					var pointNodes = markerNodes[j].getElementsByTagName("point");
					dbg(" Type: " + markerType + " Points retrieved: " + pointNodes.length);
					// Route Markers
					if(markerType == "route"){
						var points = [];
						for (var k=0;k<pointNodes.length;k=k+200){
							for(var kk=k;kk<k+199;kk++){
								if(kk<pointNodes.length){
									dbg("Point["+kk+"]: "+pointNodes[kk].getAttribute("lon")+", "+pointNodes[kk].getAttribute("lat")+", "+pointNodes[k].getAttribute("elevation"));
									tempGLatLngArray.push(new GLatLng(pointNodes[kk].getAttribute("lat"),pointNodes[kk].getAttribute("lon")));
								}
							}
						}
					}
					// get the reference points markers
					if(markerType == "keyPoint"){
						for (var k=0;k<pointNodes.length;k++){
//							newPoint = new GPoint(pointNodes[k].getAttribute("lon"), pointNodes[k].getAttribute("lat"))
							newLatLng = new GLatLng(pointNodes[k].getAttribute("lat"), pointNodes[k].getAttribute("lng"))
							html = pointNodes[k].getAttribute("content");
							if(html=="")html = "Reference Point Information";
							dbg("Point["+k+"]: "+
								pointNodes[k].getAttribute("lon")+", "+
								pointNodes[k].getAttribute("lat")+
								"<br>Id: "+
								pointNodes[k].getAttribute("id")+
								"<br>Content:"+
								pointNodes[k].getAttribute("content"));
//								html += "( "+pointNodes[k].getAttribute("id")+" )";}
							markerHtmlArray.push(html);
							gMarkerArray.push(createMarker1(newLatLng, k+1, html));
//							gMarkerPointArray.push(newPoint);
							gMarkerLatLngArray.push(newLatLng);
						}
					}
				}
			}
			currentRouteId = routeId;
			currentRouteName = routeName;
			document.newRoute.newRouteName.value = routeName;
			
			document.newRoute.routeId.value = "http://2wheeltech.com/biking/gmap.php?routeId=" + routeId;
			document.newRoute.city.value = routeCity;
			document.newRoute.state.value = routeState;
			if(routeTypeId==-1){
				document.newRoute.newType.selectedIndex = 4;
			}
			else{
				document.newRoute.newType.selectedIndex = routeTypeId;
			}
			document.newRoute.comments.value = routeComments;
			document.getElementById("newRoutePanel").style.display = "block";
			document.getElementById("homePanel").style.display = "none";
			document.getElementById("altDiv").style.display = "block";
			buildList = false;
			rehydrateMapFromDb();
			dbg("Returned from rehydrate");
		}
	}				
	request.send(null);
}



function mailer(content, fromAddress, routeName, routeId) {
	request = GXmlHttp.create();
	request.open("POST", "mailer.php", true);
	data = "content="+escape(content)+"&fromAddress="+fromAddress+"&routeName="+routeName+"&routeId="+routeId;
	header='Content-Type:application/x-www-form-urlencoded; charset=UTF-8'; 
	request.setRequestHeader(header.split(':')[0],header.split(':')[1]);
	request.onreadystatechange = function() {
		dbg("mailer readyState:"+request.readyState);
	}
	dbg("POSTing mailer.php?"+data);
	request.send(data);
}
/*
 *   Get the altitude
 *
 *
 *   POST /XMLWebServices/TNM_Elevation_Service.asmx/getElevation HTTP/1.1
 *   Host: gisdata.usgs.net
 *   Content-Type: application/x-www-form-urlencoded
 *   Content-Length: length
 *   
 *   X_Value=string&Y_Value=string&Elevation_Units=string&Source_Layer=string&Elevation_Only=string 
 */
function getAltitude(point) {
	dbg("getAltitude");
/*
	dbg("Not done");
	return;
	
	if(debug!= '1'){return;}
*/
	var request = GXmlHttp.create();
	var result;
	dbg("GET getElevation.php?x="+point.x+"&y="+point.y);
	request.open('GET', 'getElevation.php?x=' + point.x + '&y=' + point.y, true);
	
	request.onreadystatechange = function() {
		if (request.readyState == 4) {
	    var xmlDoc = GXml.parse(request.responseText);
			dbg("responseText="+request.responseText);
			var x = xmlDoc.documentElement.childNodes[0].nodeValue;
			dbg("e: "+x);
			document.newRoute.curEle.value = x;
	  }
	}
	request.send(null);
}

// Build the temp array for the routeSaver from GPX data

function showtracks(file) {

  // Setup function to center and zoom the map appropriately
  // to display the tracks then call next function f_next
	var f_setup = function(gpx, f_next) {
		var segs = gpxGetElements(gpx, "trkseg");
		dbg("Segs="+segs.length);
		for(var j=0; j<segs.length; j++) {
			var pts = gpxGetElements(segs[j], "trkpt");
			
			dbg("Pts="+pts.length);
			for(var i=0; i<pts.length; i++){
				var lon=parseFloat(pts[i].getAttribute("lon"));
				var lat=parseFloat(pts[i].getAttribute("lat"));
				var ele = gpxGetElements(pts[i], "ele")[0];		
				var elevation = GXml.value(ele);
				dbg("Point["+i+"] lon/lat:"+lon+" / "+lat+" Elevation:"+elevation);
				if(i==0){
					dbg("add pt");
					tempgLatLngArray.push(new GPoint(lon,lat));
				}
				len = tempgLatLngArray.length;
//				if(i>0 && (tempgLatLngArray[tempgLatLngArray.length-1].x - lon > .0000001 ||
//				 					 tempgLatLngArray[tempgLatLngArray.length-1].y - lat > .0000001) ){
					dbg("add pt");
					tempgLatLngArray.push(new GPoint(lon,lat));
//				}
			}
			dbg("Return ptArray["+tempgLatLngArray.length+"]");
			f_next();
		}
	}
	// Plot the route
	var f_plot = function(gpx){
		rehydrateMapFromDb();

		document.getElementById("newRoutePanel").style.display = "block";
		document.getElementById("gpxPanel").style.display = "none";
		document.getElementById("newGpxPanel").style.display = "none";


	}
	dbg("Clear Current Route");
	clearLinkHandler();

	fetch_gpx(file, function(gpx){f_setup(gpx, f_plot);} );
	dbg("Return from fetch_gpx");
}

function addLeg(xCoord, yCoord, zCoord) {
	if (bRecordPoints) { 
		dbg("<b>addLeg</b><br>xCoord:"+xCoord+
			"<br>yCoord:"+yCoord+
			"<br>zCoord:"+zCoord);
		xArray.push(xCoord);
		yArray.push(yCoord);
		zArray.push(zCoord);
		latLngArray.push(xCoord + ',' + yCoord);
// make the coords floating so the polyline can be viewed at all zoom levels
		gLatLngArray.push(new GLatLng(parseFloat(yCoord), parseFloat(xCoord)));
		dbg("x/yArray.length="+xArray.length+"/"+yArray.length);
		updateDistances(xArray, yArray, ADD);
	}
}

	// Completely ripped off of Google
function showFloat(which) {
  document.getElementById(which).style.display = 'block';
}

function hideFloat(which) {
  document.getElementById(which).style.display = 'none';
}

function createMarker1(point, index, html) {
	dbg("<b>createMarker</b> point,index,html<br>("+point.x+","+point.y+","+index+","+html+")");
	var a = new Array(0);			
	label.length = 0;
	if(index==0){
		baseIcon = new GIcon() ;
    baseIcon.shadow = "http://www.google.com/mapfiles/shadow50.png";
		baseIcon.iconSize = new GSize(20, 34);
		baseIcon.shadowSize = new GSize(37, 34);
		baseIcon.iconAnchor = new GPoint(9, 34);
		baseIcon.infoWindowAnchor = new GPoint(9, 2);
		baseIcon.infoShadowAnchor = new GPoint(18, 25);
		var icon = new GIcon(baseIcon);
		icon.image = "http://2wheeltech.com/biking/icon/red_elec.png"
		var marker = new GMarker(point, icon);

		GEvent.addListener(marker, "click",	function() {
  			marker.openInfoWindowHtml(html);
		});
	}
	else{
		dbg("keyPoint marker");
		baseIcon = new GIcon() ;
		baseIcon.shadow = "icon/mm_20_shadow.png";	
		baseIcon.iconSize = new GSize(12, 20);
		baseIcon.shadowSize = new GSize(22, 20);
		baseIcon.iconAnchor = new GPoint(6, 18);
		baseIcon.infoWindowAnchor = new GPoint(9, 5);
		baseIcon.infoShadowAnchor = new GPoint(9, 25);
		// Create a lettered icon for this point using our icon class from above
		var letter = String.fromCharCode("A".charCodeAt(0) + index);
		var icon = new GIcon(baseIcon);
		icon.image = "http://www.google.com/mapfiles/marker" + letter + ".png";
		icon.image = "icon/mm_20_orange.png"
		var marker = new GMarker(point, icon);
		var eid = new String;
		number = index;
		a[number] = document.createElement('div');
		eid = 'id'+number;
		a[number].id= eid;
		document.getElementById("map").appendChild(a[number]);
		document.getElementById(eid).innerHTML=html;
		document.getElementById(eid).style.zIndex = 50001;
		document.getElementById(eid).style.position ='absolute';
		document.getElementById(eid).style.backgroundColor = '#f2efe9';
		document.getElementById(eid).style.display = 'none';
		var content = '<img src="icon/blank.png" alt="" style="border:1px solid black; width: 12px; height: 10px;" '+
			'onmouseover="showFloat(\''+eid+'\');" onmouseout="hideFloat(\''+eid+'\');" />';
		var content='<div style="padding: 0px 0px 13px 0px; background: url(icon/blank.png) no-repeat bottom center;">'+
			'<div onmouseover="showFloat(\''+eid+'\');" onmouseout="hideFloat(\''+eid+'\');" '+
			'style="text-align: center; padding: 2px; font-size: 0.75em; font-weight: bold;">'+
			'<img src="icon/blank.png" alt="" style="border:0px solid black; width: 12px; height: 10px;"></div>';
		content+='<div id="'+eid+'" style="position: absolute; display: none;">';
		content+=' <div style="width: 81px; background-color: #f2efe9; padding: 3px; font-size: 0.75em; color: #000; '+
			'text-align: left; border: 1px solid #f00; margin-top:15px;">'+html+'</div>';
		content+='</div></div>';
		label[number] = new TLabel();
		lid = 'label' + number;
		label[number].id = lid;
		label[number].anchorLatLng = point;
		label[number].markerOffset = new GSize (0,10);
		label[number].anchorPoint = 'center';
		label[number].content = content;
		dbg("label["+number+"]"+" latlong:"+point.x+","+point.y+
    	"<br>content:"+content+"<br>"+"tooltip["+eid+"] html:"+html);
		map.addTLabel(label[number]);				
		document.getElementById(lid).style.zIndex = 50002;
		GEvent.addListener(marker, "click", function() {
			iForm = 'Enter information for this marker.<br>It is identied as ' +html+'<br><form name="iForm"><input onchange="setIData(\''+eid+'\');"  type="text" name="iData" value="'+html+'"></form>';
			marker.openInfoWindowHtml(iForm);				
		});
	}	
	return marker;
} 

function setIData(which){
	data = document.iForm.iData.value
	document.getElementById(which).innerHTML = data;
	markerHtmlArray.pop;
	markerHtmlArray.push(data);
	dbg('setIData with '+data);
} 
/*
function floatToolTip(a,e) {
  var b = document.getElementById(a);
  e = e || window.event;
  b.style.right = e.clientX;
  b.style.top = e.clientY+20;
}
*/

function addMarker(xCoord, yCoord, html) {
	if (bRecordPoints) { 
		markerNum++;
		gMarkerArray.push(createMarker1(new GPoint(xCoord, yCoord),markerNum, html));
		gMarkerPointArray.push(new GPoint(xCoord, yCoord));
		markerArray.push(xCoord + ',' + yCoord);
		markerHtmlArray.push(html);
		dbg("addMarker<br>mHA:"+markerHtmlArray.slice(-1));
	}
}

	function updateDistances(xArray, yArray, addOrRemove){
		dbg("<b>updateDistances</b>");
		if (addOrRemove == ADD){
			fLastLeg = getLastLegDistance(xArray, yArray);
			dbg("fLastLeg="+fLastLeg);
			var dAM1=distancesArray.length-1;
			if(distancesArray[dAM1]===undefined)lastTotal = 0;
			else lastTotal = distancesArray[dAM1];
			distancesArray.push(lastTotal+fLastLeg)
			legArray.push(fLastLeg);
		} else if (addOrRemove == REMOVE) {
			dbg("distancesArray.length="+distancesArray.length+"<br>Distance="+distancesArray[distancesArray.length]);
			distancesArray.pop();
			legArray.pop();
		}
		dbg("distancesArray.length="+distancesArray.length+"<br>Distance to update="+distancesArray[distancesArray.length]);
		updateDistanceBoxes();
	}

	function updateDistanceBoxes() {
		document.controlPanel.mileage.value=returnDistanceInChosenUnits(distancesArray[distancesArray.length-1]).toFixed(2);
		var fLastLeg = 0;
		if (legArray.length > 0) {
			fLastLeg = legArray[legArray.length-1];
		}
		document.controlPanel.lastLeg.value=returnDistanceInChosenUnits(fLastLeg).toFixed(2);					
	}

	function returnDistanceInMiles(point1y, point1x, point2y, point2x) {
		d = (3963.0 * Math.acos(Math.sin(point1y/57.2958) * Math.sin(point2y/57.2958) +
				Math.cos(point1y/57.2958) * Math.cos(point2y/57.2958) *
				Math.cos((point2x/57.2958) -(point1x/57.2958))));
		if(isNaN(d)) d=0;
		return d;    
	}

	

	function initializeParameter(nameOfParameter, defaultValue){
		var returnVal = '';
		var qstringVal = getQuerystringParameter(nameOfParameter);
		if (qstringVal.length > 0) {
			returnVal = qstringVal;
		} else {
			returnVal = defaultValue;
		}
		return returnVal;
	}

zoomIncrement = function(boundsSize, dataSize, exp) {
  var new_exp;
//dbgmsg.innerHTML += "Trying exp="+exp+"<br>dS.w= "+dataSize.width+"<br>bS.w= "+boundsSize.width* Math.pow(2, exp)+"<br>dS.h= "+dataSize.height+"<br>bS.h="+boundsSize.height* Math.pow(2, exp)+"<br>";
  if ((dataSize.width > boundsSize.width * Math.pow(2, exp)) || (dataSize.height > boundsSize.height * Math.pow(2, exp))) {
    if (exp < 0)
      return exp + 1;
    new_exp = exp + 1;
  } else {
    if (exp > 0)
      return exp;
    new_exp = exp - 1;
  }
  return zoomIncrement(boundsSize, dataSize, new_exp);
} 

	

newZoomLevel = function(point1, point2) {
  var originalBounds = map.getBoundsLatLng();
  var originalZoomLevel =  map.getZoomLevel();
  var originalLatSpan = Math.abs(originalBounds.maxY - originalBounds.minY);
  var originalLongSpan = Math.abs(originalBounds.maxX - originalBounds.minX);
  var originalBounds = new GSize(originalLongSpan, originalLatSpan);
  var dataLatSpan = Math.abs(point2.y - point1.y);
  var dataLongSpan = Math.abs(point2.x - point1.x);
  var dataBounds = new GSize(dataLongSpan, dataLatSpan);
  var newZoom = originalZoomLevel + zoomIncrement(originalBounds,dataBounds, 0);
  return newZoom; 
}

	

function rehydrateMapFromDb() {	
//currently the only way it is possible for the URL to have a polyline is if the user was 
// at the time they permalinked. Thus, we set recording mode back on now.
	bRecordPoints = true;
	document.controlPanel.startRecording.value='Recording...';
	dbg("<b>rehydrateMapFromDb</b> tempGLatLngArray.length=<br>"+tempGLatLngArray.length);
	if(tempGLatLngArray.length>5000 || tempGLatLngArray.length==0){
		dbg("tempGLatLngArray.length "+tempGLatLngArray.length);
		msg.innerHTML += "<span class=error>Bad tempGLatLngArray, length="+tempGLatLngArray.length+"</span><br>";
	}
	var bounds = new GLatLngBounds();
	for(var j=0;j<tempGLatLngArray.length;j++){
		var lat = tempGLatLngArray[j].y;
		var lng = tempGLatLngArray[j].x;
		bounds.extend(tempGLatLngArray[j]); 
		dbg(j+"lat/lng= "+lat+", "+lng+
			"<br>bounds: "+bounds);
		addLeg(lng, lat);
	}
/* get altitude if we don't have it.  NOT IMPLEMENTED YET
	for(j=0;j<tempGLatLngArray.length;j++){
		getAltitude(tempGLatLngArray[j]);
	}
*/
	tempGLatLngArray.splice(0,tempGLatLngArray.length);

	lat1 = bounds.getSouthWest().lat();
	lat2 = bounds.getNorthEast().lat();
	lat = (lat1+lat2)/2;
	lng1 = bounds.getSouthWest().lng();
	lng2 = bounds.getNorthEast().lng();
	lng = (lng1+lng2)/2;
	dbg("lat1: "+lat1+
		"<br>lat2: "+lat2+
		"<br>lng1: "+lng1+
		"<br>lng2: "+lng2+
		"<br>lat: "+lat+
		"<br>lng: "+lng);
	
	center = new GLatLng(lat,lng);
	dbg("center: "+center);
	zoom = map.getBoundsZoomLevel(bounds);
	dbg("center: "+center.lat()+"-"+center.lng()+
		"<br>zoom: "+zoom);
	map.setCenter(center,zoom);
	map.panTo(center);
	
//	map.centerAndZoomOnBounds(bounds); 		
//gLatLngArray should have been fully repopulated during 
//recursive calls to addLeg
	dbg("Draw polyline");
	drawPolyLine(gLatLngArray,gMarkerArray);
	dbg("Set Recording OFF");
	bRecordPoints = false;
	document.controlPanel.startRecording.value='Start Route';	
//	document.controlPanel.routeId.value=routeId;	
}



GMap.prototype.centerAndZoomOnBounds = function(bounds) {
	var span = new GSize(bounds.maxX - bounds.minX, bounds.maxY - bounds.minY);
	var center = new GPoint(bounds.minX + span.width / 2., bounds.minY + span.height / 2.);
	var newZoom = this.spec.getLowestZoomLevel(center, span, this.viewSize);
	if (this.getZoomLevel() != newZoom) {
		this.centerAndZoom(center, newZoom);
	}
	else {
		this.recenterOrPanToLatLng(center);
	}
} 



function rehydrateMapFromUrl() {
	var polyline = getQuerystringParameter('polyline');
	if (polyline.length > 0) {
		arrPoints = decodePolyline(polyline);
		//currently the only way it is possible for the URL to have a polyline is if the user was 
		//recording at the time they permalinked. Thus, we set recording mode back on now.
		bRecordPoints = true;
		document.controlPanel.startRecording.value='Recording...';
		var j = 0;
		while(j < arrPoints.length) {
			var yCoord = contractNumber(arrPoints[j++]);
			var xCoord = contractNumber(arrPoints[j++]);
			dbg("Rehyd arry:"+arrPoints[j-1]+" arrx:"+arrPoints[j]+"<br>"+
				"y:"+yCoord+" x:"+xCoord); 	
			addLeg(xCoord, yCoord);
		}
		//gLatLngArray should have been fully repopulated during 
		//recursive calls to addLeg
		drawPolyLine(gLatLngArray,gMarkerArray);
	}
}

function expandNumber(num) {
	var noMinusNum = num.replace('-','');
	var numDigitsBeforeDot = noMinusNum.indexOf('.');
	num = num.replace('\.','') 
	var digitsToGet=numDigitsBeforeDot+5;
	if (num.charAt(0)=="-") {
		num = num.substr(0,++digitsToGet);
	}else {
		num = num.substr(0,digitsToGet);
	}
	return num;
}

function contractNumber(num) {
	var numObj = new String(num);
	var lenNum = numObj.length;
	var decimalLoc = lenNum-5;
	var afterDecimal = numObj.substr(decimalLoc, 5);
	var beforeDecimal = numObj.substr(0, decimalLoc);
	return beforeDecimal + '.' + afterDecimal;
}



function prepPointArray1(latLngArray){
	var sReturn = '';
	for (i=0;i<latLngArray.length;i++){		
		sReturn += new String(latLngArray[i].y) + ',' + new String(latLngArray[i].x);			
		if (i<latLngArray.length-1)
			sReturn += ',';		
	}		
	return sReturn;	
}

function prepArray(anyArray){
	var sReturn = '';
	for (i=0;i<anyArray.length;i++){
		str = new String(anyArray[i]);
		sReturn += str;
		if (i<anyArray.length-1){
			sReturn += '|';
		}
	}
	return sReturn;
}

function prepPointArray(latLngArray){
	var sReturn = '';
	for (i=0;i<latLngArray.length;i++){
		sReturn += (expandNumber(new String(latLngArray[i].y)) + ',' + expandNumber(new String(latLngArray[i].x)));
		if (i<latLngArray.length-1)
			sReturn += ',';
	}
	return sReturn;
}

function getLastLegDistance(xArray, yArray){
	var distanceToReturn = 0;
	lastPointIdx = xArray.length - 1;
	secondToLastPointIdx = xArray.length - 2;
	if (xArray.length > 1) {
		var fLastLeg;
		distanceToReturn = returnDistanceInMiles(yArray[lastPointIdx], xArray[lastPointIdx], 
			yArray[secondToLastPointIdx], xArray[secondToLastPointIdx]);
	}
	return distanceToReturn;
}

function removeLastLeg() {
	if (xArray.length > 0) {
		dbg("<b>removeLastLeg</b><br>");
		xArray.pop();
		yArray.pop();			
		latLngArray.pop();
		gLatLngArray.pop();
		dbg("x/yArray length="+xArray.length+"<br>latLngArray length="+latLngArray.length);
		drawPolyLine(gLatLngArray,markerArray);
		updateDistances(xArray, yArray, REMOVE);
	} else {
		alert('No points to remove');
	}
}



function encodePolyline(a) {
	var p = a.split(',');
	var d = '';
	var xo=0;
	var yo=0;
	for(c=0;c<p.length;c+=2) {
		x = p[c];
		xd = x - xo;
		xo = x;
		f = (Math.abs(xd) << 1) - (xd<0);
		do {
			e = f & 31;
			f>>=5;
			if(f){e|=32};
			d+=String.fromCharCode(e+63);
		} while(f!=0);
		y = p[c+1];
		yd = y - yo;
		yo = y;
		f = (Math.abs(yd)<<1)-(yd<0);
		do {
			e = f & 31;
			f>>=5;
			if(f){e|=32};
			d+=String.fromCharCode(e+63);
		} while (f != 0);
	}
	return d;
} 

function getQuerystringParameter(paramName){
	var sReturnStr = '';
	var queryStringObj = new String(location.href)
	var paramNameObj = new String(paramName+'=');
	//queryStringObj = queryStringObj.toLowerCase();
	paramNameObj = paramNameObj.toLowerCase();
	//parameters were sent
	if (queryStringObj.indexOf('?') > -1) {
		var qStringArray = queryStringObj.split('?');
		if (qStringArray[1].length > 0) {
			var allParams = qStringArray[1]
			var paramArray = allParams.split("&");
			for (i=0; i<= paramArray.length-1; i++){
				var origCaseFullParam = paramArray[i];
				var lcaseFullParam = paramArray[i].toLowerCase();
				if (lcaseFullParam.indexOf(paramNameObj) > -1){
						sReturnStr =  unescape(origCaseFullParam.substr(paramNameObj.length));
					}
					else if(lcaseFullParam.indexOf(paramName) > -1){
						sReturnStr = '1';
					}
					if(sReturnStr.length==0)sReturnStr='0';
				}
			}
		}
		return sReturnStr;
	}

	

	function returnPermalinkString(){
		var curCenterX = map.getCenterLatLng().x;
		var curCenterY = map.getCenterLatLng().y;
		var sPoints = '';
		if (gLatLngArray.length > 0) {
			sPoints = encodePolyline(prepPointArray(gLatLngArray));
		}
		var locationString = new String(location.href);
		var locationArr = locationString.split('?');
		locationString = locationArr[0];
		return (locationString + '?centerX=' + escape(curCenterX) + '&centerY=' + escape(curCenterY) + '&zl=' + new String(map.getZoomLevel()) + '&fl=' + createFeatureListString() + '&polyline=' + escape(sPoints));
	}

	function createFeatureListString() {
		var sResult;
		sResult = ((map.getCurrentMapType()==G_SATELLITE_TYPE) ? 's' : 'm');
//		sResult += "-";
		return sResult;
	}

	function createTinyURL() {
		document.getElementById("url").value = returnPermalinkString();
		document.tinyUrlForm.submit();
	}

	function createPermalink(){
		var curCenterX = map.getCenterLatLng().x;
		var curCenterY = map.getCenterLatLng().y;
		var sPoints = '';
		if (gLatLngArray.length > 0) {
			sPoints = encodePolyline(prepPointArray(gLatLngArray));
		}
		var locationString = new String(location.href);
		var locationArr = locationString.split('?');
		locationString = locationArr[0];
		var paramString = '?centerX=' + escape(curCenterX) + '&centerY=' + escape(curCenterY) + '&zl=' + new String(map.getZoomLevel()) + '&fl=' + createFeatureListString() + '&polyline=' + escape(sPoints);
		if(sPoints.length==0){
			alert("No route created");
		}
		else{
			location.href=locationString + paramString;
			if(document.newRoute.email.value=="" || document.newRoute.newRouteName.value==""){
				alert("Please enter your email address\nand a Route Name\n to submit a route\nRoute not saved");
			}
			else{
				mailer(escape(returnPermalinkString()),document.newRoute.email.value, document.newRoute.newRouteName.value);
			}
		}
	}	

	function decodePolyline(a) {
		var b=a.length;
		var c=0;
		var d=new Array();
		var e=0;
		var f=0;
		while(c < b){
		var g;
		var h=0;
		var i=0;
		do{
			g=a.charCodeAt(c++)-63;
			i = i | (g&31)<<h;
			h = h + 5
		}while(g>=32);
		var l;
		if (i & 1){ 			
			l = ~(i >> 1); 	
		} else {				
			l = i >> 1; 	
		}
		e = e + l;
		d.push(e);
		h=0;
		i=0;
		do{
			g=a.charCodeAt(c++)-63;
			i = i | (g&31)<<h;
			h = h + 5;
		}while(g>=32);
		var m
		if (i & 1)
			m = ~(i >> 1);
		else
			m = i >> 1
		f = f + m;
		d.push(f)
	}
	return d;
}

function clearCurrentRoute(){
	bRecordPoints=true;
	distancesArray.splice(1,distancesArray.length-1);
	legArray.splice(0,legArray.length);
	latLngArray.splice(0,latLngArray.length);
	gLatLngArray.splice(0,gLatLngArray.length);
	xArray.splice(0,xArray.length);
	yArray.splice(0,yArray.length);
	markerArray.splice(0,markerArray.length);
	gMarkerArray.splice(0,gMarkerArray.length);
	for(i=0; i<label.length; i++){
		map.removeTLabel(label[i]);
	}
	label.splice(0,label.length);
	document.controlPanel.mileage.value='0';
	document.controlPanel.lastLeg.value='0';					
	map.clearOverlays();
	bRecordPoints=false;
	document.controlPanel.startRecording.value='Start Route';
}



function clearLinkHandler(){
	var clearLink = 0;
	document.controlPanel.startRecording.value='Start Route';
	bRecordPoints = false;
	if (gLatLngArray.length>0) {
		if (confirm("Are you sure you want to clear the route you've got displayed?\n"+
			"Clicking OK to will clear all points and stop recording.\n"+
			"Clicking Cancel will continue recording and leave points as they are.\n"+
			"When ready to save this route, you must enter the route name, city and state.\n\n"+
			"Comments are optional.")) {
			clearLink = 1;
		}
	}
	else clearLink = 1;
	
	if(clearLink==1){
		//distances array slightly different from all the other arrays;
		//it is initialized with a first element of 0.
		distancesArray.splice(1,distancesArray.length-1);
		legArray.splice(0,legArray.length);
		latLngArray.splice(0,latLngArray.length);
		gLatLngArray.splice(0,gLatLngArray.length);
		xArray.splice(0,xArray.length);
		yArray.splice(0,yArray.length);
		markerArray.splice(0,markerArray.length);
		gMarkerArray.splice(0,gMarkerArray.length);
		for(i=0; i<label.length; i++){
			map.removeTLabel(label[i]);
		}
		label.splice(0,label.length);
		document.controlPanel.mileage.value='0';
		document.controlPanel.lastLeg.value='0';
		document.newRoute.newRouteName.value="";
		document.newRoute.city.value="";
		document.newRoute.newType.value="";
		document.newRoute.state.value="";
		document.newRoute.comments.value="";
							
		map.clearOverlays();
		document.getElementById("newRoutePanel").style.display = "block";
		document.getElementById("routeQueryPanel").style.display = "none";
		document.getElementById("gpxPanel").style.display = "none";
		document.getElementById("routeListDiv").style.display = "none";
		document.getElementById("homePanel").style.display = "none";
		
	}
}

function nextLevel(){
	//thanks to Matt @ google maps group, http://groups-beta.google.com/group/Google-Maps/browse_frm/thread/a6ff645e0cc619c7/f23bd3f1258adcea?q=random+levels&rnum=1#f23bd3f1258adcea
	var sReturnChar
	var r = Math.random();
	//if (r < 0.65) 
	//	sReturnChar = '?';
	//
	//else if (r < 0.92) 
	//	sReturnChar = '@';
	//	
	//else if (r < 0.97)
		 sReturnChar = 'A';
   return sReturnChar
}

// Create a base icon for all of our markers that specifies the
// shadow, icon dimensions, etc.
var baseIcon = new GIcon();
baseIcon.shadow = "http://www.google.com/mapfiles/shadow50.png";
baseIcon.iconSize = new GSize(20, 34);
baseIcon.shadowSize = new GSize(37, 34);
baseIcon.iconAnchor = new GPoint(9, 34);
baseIcon.infoWindowAnchor = new GPoint(9, 2);
baseIcon.infoShadowAnchor = new GPoint(18, 25);

// Create our "tiny" marker icon
var tinyicon = new GIcon();
tinyicon.image = "http://labs.google.com/ridefinder/images/mm_20_orange.png";
tinyicon.shadow = "http://labs.google.com/ridefinder/images/mm_20_shadow.png";
tinyicon.iconSize = new GSize(12, 20);
tinyicon.shadowSize = new GSize(22, 20);
tinyicon.iconAnchor = new GPoint(6, 20);
tinyicon.infoWindowAnchor = new GPoint(5, 1);

// Creates a marker whose info window displays the letter corresponding
// to the given index.
function createMarker(point, index) {
	var mile = index.toString(10);

	dbg("mile = "+mile);
	dbg("index = "+index);
  var icon = new GIcon(baseIcon);
//  icon.image = "http://www.2wheeltech.com/biking/icon/marker" + Math.floor(index) + ".png";
  icon.image = "http://2wheeltech.com/biking/markers/numbered_marker.php?image=pushpins/webhues/087.png&text="+Math.floor(index);

	var title = "Mile Marker:"+mile
  var marker = new GMarker(point, {icon:icon, title:title});

  GEvent.addListener(marker, "click", function() {
    marker.openInfoWindowHtml("Mile Marker:" + mile);
  });
  return marker;
}


// === The basis of the arrow icon information ===
var arrowIcon = new GIcon();
arrowIcon.iconSize = new GSize(24,24);
arrowIcon.shadowSize = new GSize(1,1);
arrowIcon.iconAnchor = new GPoint(12,12);
arrowIcon.infoWindowAnchor = new GPoint(0,0);
      
// === Returns the bearing in degrees between two points. ===
// North = 0, East = 90, South = 180, West = 270.
var degreesPerRadian = 180.0 / Math.PI;

function bearing( from, to ) {
  // See T. Vincenty, Survey Review, 23, No 176, p 88-93,1975.
  // Convert to radians.
  var lat1 = from.latRadians();
  var lon1 = from.lngRadians();
  var lat2 = to.latRadians();
  var lon2 = to.lngRadians();

  // Compute the angle.
  var angle = - Math.atan2( Math.sin( lon1 - lon2 ) * Math.cos( lat2 ), Math.cos( lat1 ) * Math.sin( lat2 ) - Math.sin( lat1 ) * Math.cos( lat2 ) * Math.cos( lon1 - lon2 ) );
  if ( angle < 0.0 )
		angle  += Math.PI * 2.0;

  // And convert result to degrees.
  angle = angle * degreesPerRadian;
  angle = angle.toFixed(1);

  return angle;
}
 
// === A function to create the arrow head at the end of the polyline ===
function arrowHead(points) {
  // == obtain the bearing between the last two points
  var p1=points[points.length-1];
  var p2=points[points.length-2];
  var dir = bearing(p2,p1);
  // == round it to a multiple of 3 and cast out 120s
  var dir = Math.round(dir/3) * 3;
  while (dir >= 120) {dir -= 120;}
  // == use the corresponding triangle marker 
  arrowIcon.image = "http://www.google.com/intl/en_ALL/mapfiles/dir_"+dir+".png";
  map.addOverlay(new GMarker(p1, arrowIcon));
}

// === A function to put arrow heads at intermediate points
function midArrows(points) {
  for (var i=1; i < points.length-1; i++) {  
    var p1=points[i-1];
    var p2=points[i+1];
    var dir = bearing(p1,p2);
    // == round it to a multiple of 3 and cast out 120s
    var dir = Math.round(dir/3) * 3;
    while (dir >= 120) {dir -= 120;}
    // == use the corresponding triangle marker 
    arrowIcon.image = "http://www.google.com/intl/en_ALL/mapfiles/dir_"+dir+".png";
    map.addOverlay(new GMarker(points[i], arrowIcon));
  }
}
  
function drawPolyLine(gLatLngArray,gMarkerArray){
 	map.clearOverlays();
	//this function may be called from removeLastLeg, in which case 
	//we still want to clear points (above) but dont want to draw a new one.

	if (gLatLngArray.length > 0) {
		//draw route
			
		var style = { 
			color: '#ff0000',
//			arrowsEvery: 500,
//			beginArrow: true,
//			endArrow: false,
			opacity: .7,
			weight:5
		};
		dbg("Create / Draw gPolyline");
		dbg("gLatLngArray.length="+gLatLngArray.length);
		
		
		for(i=0;i<gLatLngArray.length;i=i+199){
			if(i+200<gLatLngArray.length){
				j=i+200;
			}
			else{
				j=gLatLngArray.length;
			}
			dbg("draw segment point "+i+" to "+j);
			map.addOverlay(new GPolyline(gLatLngArray.slice(i,j),color='#0000ff',weight=2,opacity=0.7));
		}

		//start
		dbg("Start of polyline");
		
		var point = gLatLngArray[0];
		var ticon = new GIcon(tinyicon);
		map.addOverlay(new GMarker(point,{icon:ticon, title:"Start"}));

		var k=1;
		var tDist = 0;
		var markerDist = 10;
		for(j=0;j<gLatLngArray.length-2;j++){
			var distance = gLatLngArray[j+1].distanceFrom(gLatLngArray[j]); 
// convert meters to miles
			var distanceToShow = distance*0.000621371;
			if(isNaN(distanceToShow)) distanceToShow = 0.0;
			dbg("Dist="+tDist+" distanceToShow="+distanceToShow+" Computed="+Math.floor(tDist/markerDist));
			tDist = tDist+distanceToShow;
			if(Math.floor(tDist/markerDist)>=k){
				dbg("Add mile marker: "+k*10);	
				if((tDist+distanceToShow)-Math.floor(tDist+distanceToShow)>0){
					dbg("Compute a new marker for the "+k*10+" mile marker");
					map.addOverlay(createMarker(gLatLngArray[j+1], tDist.toFixed(2)));
				}
				else {
					dbg("Add marker at "+k*10+" mile marker");
					map.addOverlay(createMarker(gLatLngArray[j+1], k));
				}
				k++;
			}
		}
		

		dbg("End polyline");
 		var marker = new GMarker(gLatLngArray[gLatLngArray.length-1],{title:"Fin:"+tDist.toFixed(2)});
  	map.addOverlay(marker);
// add arrows to the ends of polylines.  Break it up into a number of sections so we see a reasonable number
// of arrow heads
		if(gLatLngArray.length<50) inc = gLatLngArray.length/4;
		else if(gLatLngArray.length<500) inc = gLatLngArray.length/20;
		else inc = gLatLngArray.length/50;
		for(j=0;j<gLatLngArray.length;j=j+inc){
			k=j+inc-1;
			if(k>gLatLngArray.length)k=gLatLngArray.length;
			arrowHead(gLatLngArray.slice(j,k));
		}
	}
	if (gMarkerArray.length > 0) {
		dbg("All other markers");
		for(var i=0;i<=gMarkerArray.length;i++){
  		map.addOverlay(gMarkerArray[i]);
		}   	
	}    
}

function flipMileage(){
	var multiplier = getCurrentMultiplier();
	applyUnitsMultiplier(document.controlPanel.mileage);
	applyUnitsMultiplier(document.controlPanel.lastLeg);
}

function getCurrentMultiplier(){
	var unitInput = document.controlPanel.units;
	var curValue;
	if (unitInput[0].checked) {
		curValue = MILES;
	} else if (unitInput[1].checked) {
		curValue = KILOMETERS;
	}
	var multiplier;
	if (curValue==KILOMETERS) {
		multiplier = 1.609345;
	} else {
		multiplier = 1.0;
	}
	return multiplier;
}

function returnDistanceInChosenUnits(valueToApplyTo){
	var multiplier = getCurrentMultiplier();
	return valueToApplyTo * multiplier;
}

// Web Map Service map types.

function WMSCreateMap( name, copyright, baseUrl, layer, minResolution, maxResolution, urlArg )
    {
    var tileLayer = new GTileLayer( new GCopyrightCollection( copyright), minResolution, maxResolution );
    tileLayer.baseUrl = baseUrl;
    tileLayer.layer = layer;
    tileLayer.getTileUrl = WMSGetTileUrl;
    tileLayer.getCopyright = function () { return copyright; };
    var tileLayers = [ tileLayer ];
    return new GMapType( tileLayers, G_SATELLITE_MAP.getProjection(), name, { errorMessage: "Data Not Available", urlArg: 'o' } );
    }

function WMSGetTileUrl( tile, zoom )
    {
    var southWestPixel = new GPoint( tile.x * 256, ( tile.y + 1 ) * 256);
    var northEastPixel = new GPoint( ( tile.x + 1 ) * 256, tile.y * 256);
    var southWestCoords = G_NORMAL_MAP.getProjection().fromPixelToLatLng( southWestPixel, zoom );
    var northEastCoords = G_NORMAL_MAP.getProjection().fromPixelToLatLng( northEastPixel, zoom );
    var bbox = southWestCoords.lng() + ',' + southWestCoords.lat() + ',' + northEastCoords.lng() + ',' + northEastCoords.lat();
    return this.baseUrl + '?VERSION=1.1.1&REQUEST=GetMap&LAYERS=' + this.layer + '&STYLES=&SRS=EPSG:4326&BBOX=' + bbox + '&WIDTH=256&HEIGHT=256&FORMAT=image/jpeg&BGCOLOR=0xCCCCCC&EXCEPTIONS=INIMAGE';
    }

