var map;
var overlays = [];
var tracknames = new Array();
var trackindex = new Array();
var colors = [ '#0000ff', '#ff0000', '#00ff00', '#ff00ff' ];
var gpxlistxml = null;

var gpxlistfile = "/~dorm/gps/gpxlist.xml";

google.load("maps", "2.x");

function maps_initialize() {

	resizemap();
	map = new google.maps.Map2(document.getElementById("map"));

	map.setUIToDefault();
	map.setMapType(G_PHYSICAL_MAP);

	gpxlist = GDownloadUrl(gpxlistfile, function(data, respcode) {
		gpxlistxml = GXml.parse(data);
		setup_GPXSelect();

		map.addControl(new GPXSelect());

		if(window.location.hash.indexOf("/") != -1) {
			// a track was already selected
			selectgpx("/~dorm/gps/" + window.location.hash.substring(1));
		} else {
			// track markers
			trackmarkers(window.location.hash.substring(1));
		}
	});

	window.onresize = resizemap;

}

google.setOnLoadCallback(maps_initialize);


function GPXSelect() {
}


function setup_GPXSelect() {

	GPXSelect.prototype = new google.maps.Control();

	GPXSelect.prototype.initialize = function(themap) {
		var gpx_selector = document.createElement("select");
		gpx_selector.id = 'gpx_selector';
		gpx_selector.title = "Choose a Trace";
		gpx_selector.style.font = '11px Verdana';
		gpx_selector.style.backgroundColor = '#FFFFFF';

		var opt = document.createElement("option");
		opt.value = "";
		opt.appendChild(document.createTextNode('Choose a Trace'));
		opt.style.fontWeight = 'bold';
		gpx_selector.appendChild(opt);

		xml = gpxlistxml;
		var selectindex = 1;

		var sections = xml.documentElement.getElementsByTagName("section");
		for(i = 0; i < sections.length; i++) {
			var opt = document.createElement("option");
			opt.value = sections[i].getAttribute("value");
			opt.appendChild(document.createTextNode('-- ' + sections[i].getAttribute("value") + ' --'));
			opt.style.fontWeight = 'bold';
			gpx_selector.appendChild(opt);
			trackindex[sections[i].getAttribute("value")] = selectindex;
			selectindex++;

			var files = sections[i].getElementsByTagName("gpx");
			for(j = 0; j < files.length; j++) {
				var opt = document.createElement("option");
				opt.value = files[j].getAttribute("file");
				opt.appendChild(document.createTextNode(files[j].getAttribute("name") + " (" + files[j].getAttribute("date") + ")"));
				opt.style.textIndent = '15px';
				gpx_selector.appendChild(opt);
				tracknames[files[j].getAttribute("file")] = files[j].getAttribute("name") + " (" + files[j].getAttribute("date") + ")";
				trackindex[files[j].getAttribute("file")] = selectindex;
				selectindex++;
			}
		}

		GEvent.addDomListener(gpx_selector, "change", function() {
			selectgpx_form();
		} );

		var color_selector = document.createElement("select");
		color_selector.id = 'color_selector';
		color_selector.title = "Choose a Color Option";
		color_selector.style.font = '11px Verdana';
		color_selector.style.backgroundColor = '#FFFFFF';

		var opt = document.createElement("option");
		opt.value = "track";
		opt.appendChild(document.createTextNode('Color by Track'));
		color_selector.appendChild(opt);

		opt = document.createElement("option");
		opt.value = "elevation";
		opt.appendChild(document.createTextNode('Color by Elevation'));
		color_selector.appendChild(opt);

		opt = document.createElement("option");
		opt.value = "speed";
		opt.appendChild(document.createTextNode('Color by Speed'));
		color_selector.appendChild(opt);

		GEvent.addDomListener(color_selector, "change", function() {
			color_form();
		} );

		var parent_div = document.createElement("div");
		parent_div.appendChild(gpx_selector);
		parent_div.appendChild(color_selector);
		themap.getContainer().appendChild(parent_div);
		return parent_div;

	}

	GPXSelect.prototype.getDefaultPosition = function() {
		return new GControlPosition(G_ANCHOR_TOP_LEFT, new GSize(75, 7));
	}

}


function color_form() {

	var color = document.getElementById("color_selector");


}

function selectgpx_form() {

	var select = document.getElementById("gpx_selector");
	if(select.options[select.selectedIndex].value.indexOf("/") != -1) {
		selectgpx(select.options[select.selectedIndex].value);
	} else {
		trackmarkers(select.options[select.selectedIndex].value);
	}

}


function selectgpx(gpxfile) {

	clearmap();

	var gpx = GDownloadUrl(gpxfile, function(data, respcode) {
		var xml = GXml.parse(data);

		var bounds = xml.documentElement.getElementsByTagName("bounds");
		var trackbounds;
		if(bounds.length > 0) {
			bounds = bounds[0];
			var minlat = bounds.getAttribute("minlat");
			var minlon = bounds.getAttribute("minlon");
			var maxlat = bounds.getAttribute("maxlat");
			var maxlon = bounds.getAttribute("maxlon");

			trackbounds = new google.maps.LatLngBounds(new google.maps.LatLng(minlat, minlon),
				new google.maps.LatLng(maxlat, maxlon));
		}

		var color = document.getElementById("color_selector");

		if(color.options[color.selectedIndex].value == "track") {

			var coloridx = 0;
			var tracks = xml.documentElement.getElementsByTagName("trk");

			for(var i=0; i < tracks.length; i++) {
				var name = tracks[i].getElementsByTagName("name");
				if(name.length > 0) {
					name = name[0].textContent;
				} else {
					name = "";
				}

				var segments = tracks[i].getElementsByTagName("trkseg");
				var thisbound;
				for(var j=0; j < segments.length; j++) {
					thisbound = addsegment(segments[j], name, coloridx++, (bounds.length == 0));
				}

				if(bounds.length == 0) {
					if(trackbounds == undefined) {
						trackbounds = thisbound;
					} else {
						trackbounds.extend(thisbound.getSouthWest());
						trackbounds.extend(thisbound.getNorthEast());
					}
				}
			}

		} else {

			// color by speed or elevation

		}


		map.setCenter(trackbounds.getCenter());
		map.setZoom(map.getBoundsZoomLevel(trackbounds));
		map.savePosition();

	});

	document.title = "dorm.org Maps: " + tracknames[gpxfile];

	window.location.hash = gpxfile.substring(11);

	var select = document.getElementById("gpx_selector");
	select.selectedIndex = trackindex[gpxfile];

}


function addsegment(segment, name, coloridx, needbounds) {

	var trackpoints = segment.getElementsByTagName("trkpt");
	if (trackpoints.length == 0) {
		return; //latlngbounds;
	}

	var pointarray = [];

	// process first point
	var lastlon = parseFloat(trackpoints[0].getAttribute("lon"));
	var lastlat = parseFloat(trackpoints[0].getAttribute("lat"));
	var latlng = new GLatLng(lastlat,lastlon);
	pointarray.push(latlng);

	// Create a marker at the begining of each track segment
	var routeicon = new google.maps.Icon();
	routeicon.image = "images/Green_dot_7px.gif";
	routeicon.iconAnchor = new google.maps.Point(3, 3);
	var marker = new google.maps.Marker(latlng, { title: name, icon: routeicon });
	overlays.push(marker);
	map.addOverlay(marker);

	// prep LatLngBounds object if we need to calculate the bounds of this segment
	var startlatlon = new google.maps.LatLng(trackpoints[0].getAttribute("lat"), trackpoints[0].getAttribute("lon"));
	var segbounds = new google.maps.LatLngBounds(startlatlon, startlatlon);

	for (var i = 0; i < trackpoints.length; i++)
	{
		var lon = parseFloat(trackpoints[i].getAttribute("lon"));
		var lat = parseFloat(trackpoints[i].getAttribute("lat"));

		lastlon = lon;
		lastlat = lat;
		latlng = new GLatLng(lat,lon);
		pointarray.push(latlng);

		if(needbounds) {
			segbounds.extend(latlng);
		}

	}

	var routeicon = new google.maps.Icon();
	routeicon.image = "images/Red_dot_7px.gif";
	routeicon.iconAnchor = new google.maps.Point(3, 3);
	var marker = new google.maps.Marker(latlng, { title: name, icon: routeicon });
	overlays.push(marker);
	map.addOverlay(marker);

	var polyline = new GPolyline(pointarray, colors[coloridx % colors.length], 4);

	overlays.push(polyline);

	map.addOverlay(polyline);

	return segbounds;
}


function trackmarkers(section) {

	clearmap();

	// centered on colorado
	map.setCenter(new google.maps.LatLng(39.02, -105.80), 7);

	xml = gpxlistxml;

	var sections = xml.documentElement.getElementsByTagName("section");
	for(i = 0; i < sections.length; i++) {

		if((section == sections[i].getAttribute("value")) || (section == "")) {

			var files = sections[i].getElementsByTagName("gpx");
			for(j = 0; j < files.length; j++) {

				// need to move this stuff out somewhere else?
				var point = new google.maps.LatLng(files[j].getAttribute("lat"), files[j].getAttribute("lon"));
				var marker = new google.maps.Marker(point, 
					{ title: files[j].getAttribute("name") } );
				var name = files[j].getAttribute("name");
				var date = files[j].getAttribute("longdate");

				sectionname = sections[i].getAttribute("value");

				html = '<div class="infowindow">' +
					'<b><a href="" onclick="selectgpx(' + "'" + files[j].getAttribute("file") + "'" + '); return false;">' + 
					name + '</a></b> (' +
					'<a href="" onclick="trackmarkers(' + "'" + sectionname + "'" + '); return false;">' + 
					'All ' + sectionname + '</a>)<br>' + "\n" +
					date + '<br>' + "\n" +
					'Distance: <b>' + files[j].getAttribute("distance") + ' miles</b><br>' + "\n" +
					'Start Elevation: <b>' + addcommas((files[j].getAttribute("startele") * 3.2808399).toFixed(0)) + ' feet</b><br>' + "\n" +
					'Max Elevation: <b>' + addcommas((files[j].getAttribute("maxele") * 3.2808399).toFixed(0)) + ' feet</b>' +
					'</div>';
				marker.bindInfoWindowHtml(html);

				overlays.push(marker);
				map.addOverlay(marker);

			}

		}

	}


	var select = document.getElementById("gpx_selector");
	select.selectedIndex = trackindex[section];

	if(section != "") {
		window.location.hash = section;
		document.title = "dorm.org Maps: " + section;
	} else {
		window.location.hash = "#";
		document.title = "dorm.org Maps: All Tracks";
	}

}





function clearmap() {

	for(var i = 0; i < overlays.length; i++) {
		map.removeOverlay(overlays[i]);
	}
	overlays = [];

}


function resizemap() {
	mapdiv = document.getElementById("map");
	mapdiv.style.width = document.documentElement. clientWidth + "px";
	mapdiv.style.height = document.documentElement. clientHeight + "px";
}




function addcommas( sValue ) { 
	var sRegExp = new RegExp('(-?[0-9]+)([0-9]{3})');

	while(sRegExp.test(sValue)) { 
		sValue = sValue.replace(sRegExp, '$1,$2'); 
	} 
	return sValue; 
} 

