var map = 0;
var zoom = 14;
var geocoder = null;

var address_to = '';
var address_to_label = '';
var address_from = '';
var address_from_label = '';
var path = '';

var markers = {};

var mbp1 = 0;
var mbp2 = 0;

var dp1 = 0;
var dp2 = 0;
var distance = 0;

function loadMap () {
	geocoder = new GClientGeocoder();
	markers = {};

	if (GBrowserIsCompatible() && !map && document.mapinfo) {
		path = parsePath(document.mapinfo.route.value);
		address_to = document.mapinfo.address_to.value;
		address_to_label = document.mapinfo.address_to_label.value;
		address_from = document.mapinfo.address_from.value;
		address_from_label = document.mapinfo.address_from_label.value;
		
		map = new GMap2(document.getElementById("Gmap"));
		map.addControl(new GLargeMapControl());
		map.addControl(new GMapTypeControl());
		map.setCenter(new GLatLng(39.75, -104.87));
		
		if (address_to) { showAddress('to', address_to, address_to_label, address_from ? false : true); }
		if (address_from) {
			showAddress('from', address_from, address_from_label, false);
			mapBoundary();
		}
		if (path) {
			map.addOverlay(polyPoints(path));
			showDistance(getDistanceFromRoute(path));
		}
	}
}

function parsePath (path) {
	var coords = path.split('|');
	var points = new Array();
	for (var i=0; i<coords.length; i++) {
		var point = new Array();
		var parts = coords[i].split(',');
		point.x = parts[0];
		point.y = parts[1];
		points.push(point);
	}
	return points;
}

function showAddress (id, address, label, bubble) {
	geocoder.getLatLng(address, function (point) {
		if (!point) { alert(address+' not found!'); }
		else {
			map.setCenter(point, zoom);
			var marker = createMarker(id, point, label);
			map.addOverlay(marker);
			if (bubble) { marker.openInfoWindowHtml(label); }
		}
	});
}

function createMarker (id, point, html) {
	var marker = new GMarker(point);
	var properties = { maxWidth: 200 };
	GEvent.addListener(marker, 'click', function () { marker.openInfoWindowHtml(html, properties); });
	markers[id] = marker;
	return marker;
}

function polyPoints (points) {
	var polyline = new Array();
	for (var i=0; i<points.length; i++) { polyline.push(new GLatLng(points[i].y, points[i].x)); }
	return new GPolyline(polyline);
}


function getDistanceFromAddresses (address1, address2) {
	geocoder.getLatLng(address1, function (point) {
		if (point) { dp1 = point; }
		if (dp1 && dp2) { distance = (dp1.distanceFrom(dp2) / 1000) * 0.621371192; showDistance(distance); }
	});
	geocoder.getLatLng(address2, function (point) {
		if (point) { dp2 = point; }
		if (dp1 && dp2) { distance = (dp1.distanceFrom(dp2) / 1000) * 0.621371192; showDistance(distance); }
	});
}

function getDistanceFromRoute (points) {
	var distance = 0;
	var last_point = 0;
	for (var i=0; i<points.length; i++) {
		var point = new GLatLng(points[i].y, points[i].x);
		if (last_point) { distance += m2mi(last_point.distanceFrom(point)); }
		last_point = point;
	}
	return distance;
}

function showDistance (distance) {
	var lbox = document.mapinfo.locations;
	var vbox = lbox ? document.getElementById('distance'+lbox.value) : null;
	if (!lbox || !vbox) { return; }
	vbox.style.display = '';
	while (vbox.firstChild) { vbox.removeChild(vbox.firstChild); }
	vbox.appendChild(document.createTextNode('('+d2text(distance)+')'));
}

function mapBoundary () {
	if (!address_to || !address_from) { return; }
	geocoder.getLatLng(address_to, function (point) {
		if (point) { mbp1 = point; }
		if (mbp1 && mbp2) {
			mapBoundaryZoom((mbp2.y - mbp1.y) / 2 + mbp1.y, (mbp2.x - mbp1.x) / 2 + mbp1.x);
		}
	});
	geocoder.getLatLng(address_from, function (point) {
		if (point) { mbp2 = point; }
		if (mbp1 && mbp2) {
			mapBoundaryZoom((mbp2.y - mbp1.y) / 2 + mbp1.y, (mbp2.x - mbp1.x) / 2 + mbp1.x);
		}
	});
}

function mapBoundaryZoom (y, x) {
	var szoom = 17;
	var bound = false;
	var bound_x = Math.min(mbp1.x, mbp2.x);
	var bound_y = Math.max(mbp1.y, mbp2.y);
	map.setCenter(new GLatLng(y, x), szoom--);
	while (!bound && szoom >= 10) {
		var point = map.fromContainerPixelToLatLng(new GPoint(0, 0));
		var point_margin = map.fromContainerPixelToLatLng(new GPoint(10, 30));
		var margin_y = point.y - point_margin.y;
		var margin_x = point_margin.x - point.x;
		if (point.y > bound_y + margin_y && point.x < bound_x - margin_x) { bound = true; }
		else { map.setCenter(new GLatLng(y + margin_y, x), szoom--); }
	}
}

function m2mi (m) {
	return (m / 1000) * 0.621371192;
}

function d2text (distance) {
	var text = (Math.round(distance * 100) / 100);
	text += (text==1) ? ' mile' : ' miles';
	return text;
}
