var map;
var geo;
var dir;
var visible = false;

var initial_pos = new GLatLng(37.38448,-122.088661);
var initial_zoom = 10;

// how many segments we divide the circle into
var divisions = 18;

var tmp_radius;

function do_conversion(src,dst)
{
	var src_id = "radius_" + src;
	var src_el = document.getElementById(src_id);
	var dst_id = "radius_" + dst;
	var dst_el = document.getElementById(dst_id);

	var src_val = parseInt(src_el.value);

	if (src == "km") {
		dst_el.value = src_val * 0.62;
	} else {
		dst_el.value = src_val * 1.61;
	}
}

function get_circle_points(pt)
{
	result = Array();

	with (Math) {
		var lat = (tmp_radius/6378.137) * (180/PI);  // = radius / circumference of earth in rads
		var lng = lat/cos(pt.lat() * (PI/180));
		var interval = 360 / divisions;

		for (var i = 0; i <= 360; i += interval) {
			var rads = i * (PI/180);
			var x = pt.lng() + (lng * cos(rads));
			var y = pt.lat() + (lat * sin(rads));
			var newpt = new GLatLng(parseFloat(y), parseFloat(x), true);
			result.push(newpt);
		}
	}

	return result;
}

function on_point(pt)
{
	if (!pt) {
		alert("unknown address");
		return;
	}

	if (visible) {
		return;
	}
	visible = true;

	tmp_marker = new GMarker(pt);
	map.addOverlay(tmp_marker);

	circle_pts = get_circle_points(pt);

	var tmp_bounds = new GLatLngBounds();
	for (var i = 0; i < circle_pts.length; i++) {
		tmp_bounds.extend(circle_pts[i]);
	}
	var new_zoom = map.getBoundsZoomLevel(tmp_bounds);

	map.setCenter(pt, new_zoom);

	// Raw radius
	var line = new GPolyline(circle_pts, "#ff0000", 2, 1);
	map.addOverlay(line);

	// work on drawing the drivable radius
	drawDrivable(pt, circle_pts);
}

function drawArea(area, pts)
{
	if (pts.length < 3) {
		return;
	}

	if (area) {
		map.removeOverlay(area);
	}

	area = new GPolygon(pts, "#00ff00", 1, 1, "#00ff00", 0.3);
	map.addOverlay(area);

	return area;
}

function drawDrivable(pt, pts)
{
	if (!pts.length) {
		return;
	}

	var max_dist = tmp_radius * 1000; // in metres
	var area = null;

	var areaPoints = Array();
	var i = 0;
	var from = "";
	var to = "";
	var loadString = "";

	GEvent.addListener(dir, "load", function() {
		var polyline = dir.getPolyline();
		var dist = 0;
		var lastpt = null;

		// walk the line and see how far tmp_radius gets us along it
		for (var j = 0; j < polyline.getVertexCount()-1; j++) {
			dist += polyline.getVertex(j).distanceFrom(polyline.getVertex(j+1));
			if (dist < max_dist) {
				lastpt = polyline.getVertex(j);
			} else {
			
				break;
			}
		}

		// okay, now lastpt is as far as we can get without exceeding tmp_radius
		//var newmarker = new GMarker(lastpt);
		//map.addOverlay(newmarker);
		areaPoints.push(lastpt);
		area = drawArea(area, areaPoints);

		// move on to the next
		if (i < pts.length) {
			load_next(pt, pts, i++);
		} else {
			on_finished();
		}
	});
	GEvent.addListener(dir, "error", function() {
		// errors are common if a point on the radius is impossible to
		// reach by road.  In that case, we just move on to the next.
		if (i < pts.length) {
			areaPoints.push(pts[i]);
			area = drawArea(area, areaPoints);
			load_next(pt, pts, i++);
		} else {
			on_finished();
		}
	});

	// load the first point to start the cycle
	load_next(pt, pts, i++);
}

function load_next(pt, pts, i)
{
	from = pt.lat() + " " + pt.lng();
	to = pts[i].lat() + " " + pts[i].lng();
	loadString = "from: " + from + " to: " + to;
	dir.load(loadString, {getPolyline:true,getSteps:true});
}

function on_finished()
{
	alert("done");
	GEvent.clearListeners(dir, "load");
	GEvent.clearListeners(dir, "error");
}

function do_map()
{
	var el;

	if (visible) {
		do_wipe();
	}

	el = document.getElementById("radius_km");
	if (!el || el.value == "") {
		alert("error getting radius");
		return;
	}
	tmp_radius = el.value;

	el = document.getElementById("position");
	if (!el || el.value == "") {
		alert("error getting starting position");
		return;
	}
	geo.getLatLng(el.value, on_point);
}

function do_wipe()
{
	map.clearOverlays();
	visible = false;
}

function init_map(id)
{
	var el = document.getElementById(id)
	map = new GMap2(el);

	// config the map
	map.setMapType(G_NORMAL_MAP);
	map.addControl(new GScaleControl());
	map.addControl(new GLargeMapControl());
	map.addControl(new GMapTypeControl());

	// features
	map.enableDragging();
	map.enableDoubleClickZoom();
	map.enableScrollWheelZoom();
	map.enableContinuousZoom();

	// location
	map.setCenter(initial_pos);
	map.setZoom(initial_zoom);

	geo = new GClientGeocoder();
	dir = new GDirections();
}

