var gCurrentPoint;
var firstPointSet = false;
var step = 1;
var gDistanceLine;
var lats = Array();
var lngs = Array();

var gDistanceLines = [];
var gLineMarkers = [];
var gNumericMarkers = [];
var gDistanceLinesGarbage = [];
var gLineMarkersGarbage = [];
var gSegmentDistance = [];
var gPolygons = [];

var gDistanceControl;
var gDistanceControlDiv;
var gStopCloseControl;
var gDistanceClearControl;

// Event handler global variables
var gDistanceClickHandler;
var gDistanceMousemoveHander;
var gRecenterClickHandler;
var gClicked = false;


var NagivationTools = {
	tools: [],

	add: function (imgID) {
		var element = $(imgID);
		var action_name = element.id.replace('tool_', '');

		this.tools.push(element.id);

		element.observe('mouseover',
			function (event) {
				if(active_tool() != action_name) {
					element.src='skins/icons/icon_' + element.id + '_hover.png'
				}
			});

		element.observe('mouseout',
			function (event) {
				if(active_tool() != action_name) {
					element.src='skins/icons/icon_' + element.id + '.png'
				}
			});
	}
}

/***** Tools common functions *****/
function deactivate(tool_type) {
	switch (tool_type) {
		case "distance":
		case "draw_polygon":
		case "draw_rect":
			deactivate_distance(tool_type);
			break;
		case "remove_polygon":
			deactivate_remove_polygon();
			break;
		case "numeric_polygon":
			deactivate_numeric_polygon();
			break;
		case "zoomin":
			deactivate_zoomin();
		default:
	}
	map.closeInfoWindow();
}

/***** Measure Distance Tool *****/
/*
Add three custom controls at the lower right corner of the map.
Show the distance in one of the controls.
tool_type: distance|draw_polygon
*/
function activate_distance(tool_type) {
	var theTool = $("tool_" + tool_type);

	// Activate
	if (active_tool()  != tool_type) {
		// Deactivate the currently selected tool first.
		deactivate(active_tool());

		theTool.src='skins/icons/icon_tool_' + tool_type + '_selected.png'
		gToolStack.push(tool_type);
		gDistanceClickHandler = GEvent.addListener(map, "click", initializeLineDrawing);

		// Add distance controls
		if (active_tool() == "distance" || active_tool() == "draw_polygon") {
			gDistanceControl = new DistanceControl();
			map.addControl(gDistanceControl);
		}

		if (active_tool() == "distance") {
			gStopCloseControl = new DistanceStopControl();
			map.addControl(gStopCloseControl);
		} else if (active_tool() == "draw_polygon") {
			gStopCloseControl = new ClosePolyControl();
			map.addControl(gStopCloseControl);
		}

		gDistanceClearControl = new DistanceClearControl();
		map.addControl(gDistanceClearControl);

		//GEvent.addDomListener(document.getElementById("map"), "keyup", function (e) {
		//});
	// Deactivate
	} else if (active_tool()  == tool_type) {
		//deactivate_distance(tool_type);
		deactivate(tool_type);
	}
}


function deactivate_distance(tool_type) {
	var theTool = $("tool_" + tool_type);

	// clear the current segment and all lines, markers
	distance_clear();

	theTool.src = 'skins/icons/icon_tool_' + tool_type + '.png';
	gToolStack.pop();
	firstPointSet = false;
	GEvent.removeListener(gDistanceClickHandler);

	if(gDistanceMousemoveHander) {
		GEvent.removeListener(gDistanceMousemoveHander);
	}

	// Remove custom controls for Distance Tool
	map.removeControl(gDistanceControl);

	if (tool_type == "distance" || tool_type == "draw_polygon") {
		map.removeControl(gStopCloseControl);
	}
	map.removeControl(gDistanceClearControl);
}

function initializeLineDrawing(marker, point) {
	var close_polygon = false;

	if (active_tool()  != "distance" &&
		active_tool() != "draw_polygon"&&
		active_tool() != "draw_rect" &&
		active_tool() != "zoomin") {
		return false;
	}

	// When the first marker is clicked, close the polygon and deactivate the tool.
	// GM's default polyline click passes point as undefined, so ignore the event.
	// Custom polyline click event listener passes both marker and point.
	if (marker && (typeof(point) == 'undefined' || point == null)) {
		if (gLineMarkers.length > 0 && marker == gLineMarkers[0]) {
			point = gLineMarkers[0].getPoint();
			close_polygon = true;
		} else {
			return false;
		}
	}

	// In IE, a click event is followed by mousemove event.
	// To suppress mousemove event, use global variable indicating a click event just occurred.
	gClicked = true;

	if (firstPointSet == false) {		// Initialize: first point clicked
		if (active_tool() == "draw_rect" || active_tool() == "zoomin") {
			gDistanceMousemoveHander = GEvent.addListener(map, "mousemove", drawArea);
		} else {
			gDistanceMousemoveHander = GEvent.addListener(map, "mousemove", drawLine);
		}

		msg = "This is the first point."
		firstPointSet = true;
	} else {		// Second, third,... point clicked
		// To calculate distance, temporarily turn gClicked off.
		gClicked = false;
		step = 0;

		switch (active_tool()) {
			case "draw_rect":
				var rect = make_polygon(drawArea(point));
				distance_clear();
				msg = "Area in km2<BR>" + (rect.getArea()/1000000).toFixed(2);
				map.openInfoWindowHtml(point, msg, {suppressMapPan:true, maxWidth:300});
				return true;
				break;
			case "zoomin":
				if (gCurrentPoint.lng() < point.lng()) {
					var sw = gCurrentPoint;
					var ne = point;
				} else {
					var sw = point;
					var ne = gCurrentPoint;
				}
				var aBound = new GLatLngBounds(sw, ne);
				var aCenter = aBound.getCenter();
				map.setCenter(aCenter);

				var aZoomLevel = map.getBoundsZoomLevel(aBound);
				map.setZoom(aZoomLevel);
				distance_clear();
				return true;
				break;
			default:
				var fixed_line = new GPolyline(drawLine(point), "#ff0000", 3, 0.5);
				gDistanceLines.push(fixed_line);
				map.addOverlay(fixed_line);
				var distance = get_distance(gCurrentPoint, point);

				gSegmentDistance.push(distance);
				msg = getDistanceText();
				if (active_tool() == "draw_polygon") {
					msg += "<P>To close polygon, hit [Close it] or click on the first vertex.</p>";
				} else {
					msg += "<P>To finish drawing lines, hit [Stop].</p>";
				}
				map.openInfoWindowHtml(point, msg, {suppressMapPan:true, maxWidth:300});
		}

		// Get gClicked back to true so the mousemove event is suppressed.
		gClicked = true;
	}

	var icon = point_icon();
	var new_marker = createDistanceMarker(point, icon, msg);
	map.addOverlay(new_marker);
	gLineMarkers.push(new_marker);
	gCurrentPoint = point;

	if (close_polygon) {
		if (active_tool() == "draw_polygon") {
			turn_to_polygon();
			distance_clear();
		} else {
			distance_stop();
		}
	}

	return true;
}

function close_polygon() {
	// A polygon should have at least three points to close.
	if (gLineMarkers.length > 2) {
		var marker = gLineMarkers[0];
		initializeLineDrawing(marker, null);
	}
}

function turn_to_polygon() {
	var poly_points = [];

	for (i = 0; i < gLineMarkers.length; i++) {
		var point = gLineMarkers[i].getPoint();
		poly_points[i] = new  GLatLng(point.lat(), point.lng());
	}

	make_polygon(poly_points);
}

function make_polygon(poly_points) {
	poly_opacity = 0.4;
	line_color = "#17174D";
	poly_colors = new Array("#FFFF00", "#66FF00", "#FF33CC", "#FF0066", "#00FFFF");

	var color_index = gPolygons.length % 5;
	poly_color = poly_colors[color_index];
	var polygon = new GPolygon(poly_points, line_color, 1, 0.9, poly_color, poly_opacity);
	GEvent.addListener(polygon,"click",function(point){
		gClickedPolygon = polygon;
		if (active_tool() == "remove_polygon") {
			remove_polygon(polygon);
		} else {
        	on_click_identify(polygon, point);
		}
      });
	map.addOverlay(polygon);
	gPolygons.push(polygon);
	return polygon;
}


function createDistanceMarker(point, icon, msg) {
	var marker = new GMarker(point, icon);
	GEvent.addListener(marker, "click", function() {
    marker.openInfoWindowHtml(msg, {maxWidth:300});
  });
  return marker;
}


function getDistanceText() {
	var totalDistance = 0;
	var msg = "<P>";
	for (i = 0; i < gSegmentDistance.length; i++) {
		msg += "Segment[" + (i + 1) + "] = " + gSegmentDistance[i].toFixed(3) + "<BR>\n";
		totalDistance += gSegmentDistance[i];
	}

	msg += "Total = " + totalDistance.toFixed(3) + " nm</P>\n";

	return msg;
}

function getPolygonText(aPolygon) {
	var msg = "<TABLE class='listing'><THEAD><TR><TH>&nbsp;</TH><TH>Longitude</TH><TH>Latitude</TH></THEAD><TBODY>";
	for (var i = 0; i < aPolygon.getVertexCount() - 1; i++) {
		var aVertex = aPolygon.getVertex(i);
		msg += "<TR><TD align='right'>" + i + "</TD><TD align='right'>" + aVertex.lng().toFixed(4) + "</TD><TD align='right'>" + aVertex.lat().toFixed(4) + "</TD></TR>";
	}

	msg += "</TBODY></TABLE>";

	// find table id
	for (var i = 0; i < gPolygons.length; i++) {
		if (aPolygon == gPolygons[i]) {
			var table_id = "pt_" + i;
			break;
		}
	}
	msg += '<P><a href="javascript: void(0);" onclick="zoomin_to_polygon(\'' + table_id + '\');">Zoom to</a>';
	msg += '&nbsp;&nbsp;';
	msg += '<a href="javascript: void(0);" onclick="remove_polygon_by_id(\'' + table_id + '\');">Remove</a>';
	msg += "</P>";

	return msg;
}

function drawLine (latlong) {
	// drawLine returns array of points from which a polyline is made.
	// It doesn't return the polyline gDistanceLine itself.
	// Note gDistanceLine is a global variable and not persistent as it is removed at every mouse move.
	if (active_tool()  != "distance" && active_tool()  != "draw_polygon") {
		return false;
	}

	if (gClicked) {
		gClicked = false;
		return false;
	}
	var secondPoint = latlong;

	if (step % 3 != 0) {
		step++;
		if (step > 3) {
			step = 1;
		}
		return false;
	}

	map.closeInfoWindow();

	var linePoints = Array();
	linePoints[0] = gCurrentPoint;
	linePoints[1] = secondPoint;

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

	gDistanceLine = new GPolyline(linePoints, "#ff0000", 3, 0.5);
	GEvent.addListener(gDistanceLine,"click",function(point){
        initializeLineDrawing(gDistanceLine, point);
      });
	map.addOverlay(gDistanceLine);

	var distance = get_distance(gCurrentPoint, secondPoint);
	gDistanceControlDiv.innerHTML = distance.toFixed(3);

	return linePoints;
}

function drawArea (latlong) {
	if (active_tool()  != "draw_rect" && active_tool()  != "zoomin") {
		return false;
	}

	var secondPoint = latlong;

	if (step % 3 != 0) {
		step++;
		if (step > 3) {
			step = 1;
		}
		return false;
	}

	var lats = [];
	var lngs = [];

	lats[0] = gCurrentPoint.lat();
	lngs[0] = gCurrentPoint.lng();
	lats[1] = secondPoint.lat();
	lngs[1] = secondPoint.lng();
	var thirdPoint = new GLatLng(lats[1], lngs[0]);
	var fourthPoint = new GLatLng(lats[0], lngs[1]);

	var linePoints = Array();
	linePoints[0] = gCurrentPoint;
	linePoints[1] = thirdPoint;
	linePoints[2] = secondPoint;
	linePoints[3] = fourthPoint;
	linePoints[4] = gCurrentPoint;

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

	gDistanceLine = new GPolyline(linePoints, "#ff0000", 3, 0.5);
	GEvent.addListener(gDistanceLine,"click",function(point){
        initializeLineDrawing(gDistanceLine, point);
      });
	map.addOverlay(gDistanceLine);

	return linePoints;
}


function get_distance(gPoint1, gPoint2) {
	var point1 = [];
	point1['lon'] = gPoint1.lng();
	point1['lat'] = gPoint1.lat();
	var point2 = [];
	point2['lon'] = gPoint2.lng();
	point2['lat'] = gPoint2.lat();
	var distance = ComputeDistance(point1, point2);
	return distance;
}

function point_icon () {
	var icon = new GIcon();
	icon.image = g_ROOT_URL + BASE_URL + "images/icons/ball_red.png";
	icon.iconSize = new GSize(10, 10);
	icon.iconAnchor = new GPoint(5, 5);
	icon.infoWindowAnchor = new GPoint(5, 5);
	return icon;
}


/***** Distance Contorls *****/
// Used to show distance.
function DistanceControl () {
}

DistanceControl.prototype = new GControl();

DistanceControl.prototype.initialize = function(map) {
	gDistanceControlDiv = document.createElement("div");
	this.setButtonStyle_(gDistanceControlDiv);
	gDistanceControlDiv.appendChild(document.createTextNode("Distance"));

	map.getContainer().appendChild(gDistanceControlDiv);
	return gDistanceControlDiv;
}

DistanceControl.prototype.getDefaultPosition = function() {
  return new GControlPosition(G_ANCHOR_TOP_LEFT, new GSize(100, 6));
}

DistanceControl.prototype.setButtonStyle_ = function(button) {
	button.style.display = "inline";
	button.style.textDecoration = "none";
	button.style.backgroundColor = "white";
	button.style.border = "1px solid black";
	button.style.padding = "2px";
	button.style.marginBottom = "3px";
	button.style.textAlign = "center";
	button.style.width = "100px";
	button.style.cursor = "pointer";
}

// Stop controls
function DistanceStopControl () {
}

DistanceStopControl.prototype = new GControl();

DistanceStopControl.prototype.initialize = function(map) {
	// Stop Control
	StopControlDiv = document.createElement("div");
	this.setButtonStyle_(StopControlDiv);
	StopControlDiv.appendChild(document.createTextNode("Stop"));
	GEvent.addDomListener(StopControlDiv, "click", function() {
		distance_stop();
	});

	map.getContainer().appendChild(StopControlDiv);
	return StopControlDiv;
}

DistanceStopControl.prototype.getDefaultPosition = function() {
  return new GControlPosition(G_ANCHOR_TOP_LEFT, new GSize(213, 6));
}

DistanceStopControl.prototype.setButtonStyle_ = function(button) {
	setActionStyle(button);
}

// Clear control
function DistanceClearControl () {
}

DistanceClearControl.prototype = new GControl();

DistanceClearControl.prototype.initialize = function(map) {
	// Clear Control
	ClearControlDiv = document.createElement("div");
	this.setButtonStyle_(ClearControlDiv);
	ClearControlDiv.appendChild(document.createTextNode("Clear"));
	GEvent.addDomListener(ClearControlDiv, "click", function() {
		distance_clear();

		if (active_tool() == "draw_polygon" || active_tool() == "draw_rect") {
			clear_polygon();
		}
		map.closeInfoWindow();
	});

	map.getContainer().appendChild(ClearControlDiv);
	return ClearControlDiv;
}

DistanceClearControl.prototype.getDefaultPosition = function() {
  return new GControlPosition(G_ANCHOR_TOP_LEFT, new GSize(300, 6));
}

DistanceClearControl.prototype.setButtonStyle_ = function(button) {
	setActionStyle(button);
}

// Close polygon controls
function ClosePolyControl () {
}

ClosePolyControl.prototype = new GControl();

ClosePolyControl.prototype.initialize = function(map) {
	// Stop Control
	ClosePolyControlDiv = document.createElement("div");
	this.setButtonStyle_(ClosePolyControlDiv);
	ClosePolyControlDiv.appendChild(document.createTextNode("Close it"));
	GEvent.addDomListener(ClosePolyControlDiv, "click", function() {
		close_polygon();
	});

	map.getContainer().appendChild(ClosePolyControlDiv);
	return ClosePolyControlDiv;
}

ClosePolyControl.prototype.getDefaultPosition = function() {
  return new GControlPosition(G_ANCHOR_TOP_LEFT, new GSize(213, 6));
}

ClosePolyControl.prototype.setButtonStyle_ = function(button) {
	setActionStyle(button);
}


function setActionStyle(button) {
	button.style.display = "block";
	button.style.textDecoration = "none";
	button.style.color = "#0000cc";
	button.style.backgroundColor = "white";
	button.style.border = "1px solid black";
	button.style.padding = "2px";
	button.style.marginBottom = "3px";
	button.style.textAlign = "center";
	button.style.width = "80px";
	button.style.cursor = "pointer";

}

function distance_stop() {
	if (active_tool()  != "distance" &&
		active_tool() != "draw_polygon" &&
		active_tool() != "draw_rect" &&
		active_tool() != "zoomin") {
		return false;
	}

	// clear the current segment
	map.removeOverlay(gDistanceLine);

	// Deactivate mousemove event
	if(gDistanceMousemoveHander) {
		GEvent.removeListener(gDistanceMousemoveHander);
	}

	// Before clearing gDistanceLines and gLineMarkers,
	// put them into garbage array, so they can be removed when diactivate or clear
	for (i = 0; i < gDistanceLines.length; i++) {
		gDistanceLinesGarbage.push(gDistanceLines[i]);
	}
	// clear all markers
	for (i = 0; i < gLineMarkers.length; i++) {
		gLineMarkersGarbage.push(gLineMarkers[i]);
	}

	firstPointSet = false;
	gCurrentPoint = null;
	gDistanceLines = [];
	gLineMarkers = [];
	gSegmentDistance = [];
}

function distance_clear() {
	if (active_tool()  != "distance" &&
		active_tool() != "draw_polygon" &&
		active_tool() != "draw_rect" &&
		active_tool() != "zoomin") {
		return false;
	}

	distance_stop();

	// clear all lines
	for (i = 0; i < gDistanceLinesGarbage.length; i++) {
		map.removeOverlay(gDistanceLinesGarbage[i]);
	}
	// clear all markers
	for (i = 0; i < gLineMarkersGarbage.length; i++) {
		map.removeOverlay(gLineMarkersGarbage[i]);
	}
}

function clear_polygon() {
	for (i = 0; i < gPolygons.length; i++) {
		map.removeOverlay(gPolygons[i]);
	}

	gPolygons = [];
}


/***** Numeric polygon functions *****/
function show_numeric_polygon_popup() {
	if (active_tool()  != "numeric_polygon") {
		deactivate(active_tool());

		var tool_type = "numeric_polygon";
		var theTool = $("tool_" + tool_type);
		theTool.src='skins/icons/icon_tool_' + tool_type + '_selected.png'
		gToolStack.push(tool_type);

		// Clear the tables first to refresh
		var aDiv = $("numeric_polygon_popup_body");
		if (gPolygons.length > 3) {
			aDiv.style.height = "400px";
			aDiv.style.overflow = "auto";
		}

		var tables = aDiv.getElementsByTagName("TABLE");
		while(tables.length > 0) {
			aDiv.removeChild(tables[0]);
		}

		if (gPolygons.length > 0) {
			for (var i = 0 ; i < gPolygons.length; i++) {
				add_polygon_table(i);
				var aColor = gPolygons[i].color;
				// Note that the last point should be the same as the first point, so ignore it.
				for (var j = 0; j < gPolygons[i].getVertexCount() - 1; j++) {
					var aVertex = gPolygons[i].getVertex(j);
					add_row("ptb_" + i, j + 1, aColor, aVertex.lng(), aVertex.lat());
				}
			}
		} else {
			add_new_roi_table(0);
		}

		$("numeric_polygon_popup").show();
	} else if (active_tool() == "numeric_polygon") {
		deactivate_numeric_polygon();
	}
}

function deactivate_numeric_polygon() {
	var div = $("numeric_polygon_popup");
	div.hide();

	var tool_type = "numeric_polygon";
	var theTool = getObject("tool_" + tool_type);
	theTool.src='skins/icons/icon_tool_' + tool_type + '.png'
	gToolStack.pop();

}

function add_polygon_table(polygon_index) {
	var aTable = document.createElement("TABLE");
	aTable.id ="pt_" + polygon_index;
	aTable.className = "listing";

	var aHead = document.createElement("THEAD");
	var aRow = document.createElement("TR");

	var cellIDs = new Array(' ', 'Longitude', 'Latitude');
	for (var i = 0; i < cellIDs.length; i++) {
		// Polygon color cell
		var aCell = document.createElement("TH");
		var currenttext = document.createTextNode(cellIDs[i]);
		aCell.appendChild(currenttext);

		aRow.appendChild(aCell);
	}
	aHead.appendChild(aRow);
	aTable.appendChild(aHead);

	// TBODY
	var aBody = document.createElement("TBODY");
	aBody.id = "ptb_" + polygon_index;
	aTable.appendChild(aBody);

	// Add the generated table to DIV
	var aDiv = $("numeric_polygon_popup_body");
	aDiv.appendChild(aTable);
}


function add_row(table_body_id, row_index, color, lon, lat) {
	// row_index starts at 1
	if (color == "") {
		color = "#ffffff";
	}

	var cellValues = [];
	cellValues.push(color);
	cellValues.push(lon);
	cellValues.push(lat);

	var cellIDs = new Array('color', 'lon', 'lat');

	var table_body = $(table_body_id);

	var aRow = document.createElement("TR");

	for (i = 0; i < cellValues.length; i++) {
		// Polygon color cell
		var aCell = document.createElement("TD");
		//var currenttext = document.createTextNode("&nbsp;");
		//polyCell.appendChild(currenttext);
		if (i == 0) {
			if (row_index == 1) {
				aCell.innerHTML = '<img src="skins/icons/icon_zoomin.png" onclick="zoomin_to_polygon(\'' + table_body_id + '\');">';	// Color
			} else if (row_index == 2) {
				aCell.innerHTML = '<img src="skins/icons/icon_delete.png" onclick="remove_polygon_by_id(\'' + table_body_id + '\');">';	// Color
			} else {
				aCell.innerHTML = "&nbsp;";
			}
			aCell.style.backgroundColor = cellValues[i];
		} else {
			cellID = table_body_id + "_" + cellIDs[i] + "_" + row_index;
			aCell.innerHTML = '<input id="' + cellID + '" type="text" value="' + cellValues[i] + '" size="10" onkeypress="latlon_keypress(\'' + table_body_id + '\', this.id, event);" onblur="numeric_marker(this.id);">';
		}

		aRow.appendChild(aCell);
	}

	table_body.appendChild(aRow);
}


function zoomin_to_polygon(table_id) {
	// ie. ptb_0
	if (gPolygons.length == 0) {
		return false;
	}

	var idElements = table_id.split("_");
	var polygon_index = idElements[1];
	var aPolygon = gPolygons[polygon_index];

	var max_lon = -180;
	var max_lat = -90;
	var min_lon = 180;
	var min_lat = 90;

	for (var i = 0; i < aPolygon.getVertexCount(); i++) {
		var aPoint = aPolygon.getVertex(i);

		if (max_lon < aPoint.lng()) {
			max_lon = aPoint.lng();
		}
		if (max_lat < aPoint.lat()) {
			max_lat = aPoint.lat();
		}
		if (min_lon > aPoint.lng()) {
			min_lon = aPoint.lng();
		}
		if (min_lat > aPoint.lat()) {
			min_lat = aPoint.lat();
		}
	}
	var aBound = new GLatLngBounds(new GLatLng(min_lat, min_lon), new GLatLng(max_lat, max_lon));
	var aCenter = aBound.getCenter();
	map.setCenter(aCenter);

	var aZoomLevel = map.getBoundsZoomLevel(aBound);
	map.setZoom(aZoomLevel);
}

function remove_polygon_by_id(table_id) {
	// ie. ptb_0
	var idElements = table_id.split("_");
	var polygon_index = idElements[1];
	var aPolygon = gPolygons[polygon_index];

	remove_polygon(aPolygon);

	var aDiv = $("numeric_polygon_popup_body");
	var tables = aDiv.getElementsByTagName("TABLE");
	for (var i = 0; i < tables.length; i++) {
		if (tables[i].id == "pt_" + polygon_index) {
			aDiv.removeChild(tables[i]);
			break;
		}
	}

	// Redraw the table
	var tables = aDiv.getElementsByTagName("TABLE");
	while(tables.length > 0) {
		aDiv.removeChild(tables[0]);
	}

	if (gPolygons.length > 0) {
		for (var i = 0 ; i < gPolygons.length; i++) {
			add_polygon_table(i);

			var aColor = gPolygons[i].color;
			// Note that the last point should be the same as the first point, so ignore it.
			for (var j = 0; j < gPolygons[i].getVertexCount() - 1; j++) {
				var aVertex = gPolygons[i].getVertex(j);
				add_row("ptb_" + i, j + 1, aColor, aVertex.lng(), aVertex.lat());
			}
		}
	} else {
		add_new_roi_table(0);
	}
}

function remove_polygon(polygon) {
	repopulate_polygons(polygon);
	map.removeOverlay(polygon);
	map.closeInfoWindow();
	gClickedPolygon = null;
}

function repopulate_polygons(aPolygon) {
	var tempPolygons = [];
	//var tempPolygonColors = [];
	for (var i = 0; i < gPolygons.length; i++) {
		if (aPolygon != gPolygons[i]) {
			tempPolygons.push (gPolygons[i]);
		}
	}

	gPolygons = [];
	gPolygons = tempPolygons;
}

function latlon_keypress(parentTable, cellID, e) {
	var cellIDElements = cellID.split("_");	// cellID = ptb_lat_1 ...
	var table_id = cellIDElements[0] + "_" + cellIDElements[1] + "_";
	var	row_index = parseInt(cellIDElements[3]);

	var keyPressed  = (window.event) ?    // MSIE or Firefox?
		event.keyCode : e.keyCode;

	switch (keyPressed) {
		case Event.KEY_RETURN:

			// If the next row already exists, set focus to that row.
			// Otherwise, insert a new row.
			if (!getObject(table_id + cellIDElements[2] + "_" + (row_index + 1))) {
				color = "";
				lon = "";
				lat = "";

				add_row(parentTable,  row_index + 1, color, lon, lat);
			}
			var nextRow = $(table_id + "lon_" + (row_index + 1));
			nextRow.focus();
			break;
		case Event.KEY_DOWN:
			if (getObject(table_id + cellIDElements[2] + "_" + (row_index + 1))) {
				var nextRow = $(table_id + cellIDElements[2] + "_" + (row_index + 1));
				nextRow.focus();
			}
			break;
		case Event.KEY_UP:
			if (getObject(table_id + cellIDElements[2] + "_" + (row_index - 1))) {
				var nextRow = $(table_id + cellIDElements[2] + "_" + (row_index - 1));
				nextRow.focus();
			}
			break;
	}
}

function clear_polygon_table() {
	clear_polygon();

	// Clear the tables
	var aDiv = $("numeric_polygon_popup_body");
	var tables = aDiv.getElementsByTagName("TABLE");
	while(tables.length > 0) {
		aDiv.removeChild(tables[0]);
	}

	// Clear temporal markers.
	for (i = 0; i < gNumericMarkers.length; i++) {
		map.removeOverlay(gNumericMarkers[i]);
	}
	gNumericMarkers = [];

	add_new_roi_table(0);
}

function add_new_roi_table(index) {
	add_polygon_table(index);
	var ptb = "ptb_" + index;
	add_row(ptb, 1, "", "", "");
	add_row(ptb, 2, "", "", "");
	add_row(ptb, 3, "", "", "");
}

function add_new_roi() {
	var table_index = gPolygons.length;
	add_new_roi_table(table_index);
}

function numeric_marker(cellID) {
	// row_index starts at 1
	var cellIDElements = cellID.split("_");
	var table_id = cellIDElements[0] + "_" + cellIDElements[1] + "_";
	row_index = parseInt(cellIDElements[3]);

	var lon = $(table_id + "lon_" + row_index).value;
	var lat = $(table_id + "lat_" + row_index).value;

	if (!isNaN(parseFloat(lon)) && !isNaN(parseFloat(lat))) {
		msg = "(Longitude, Latitude) = (" + lon + ", " + lat + ")";

		var point = new GLatLng(parseFloat(lat), parseFloat(lon));
		var icon = point_icon();
		var new_marker = createDistanceMarker(point, icon, msg);

		if (row_index <= gNumericMarkers.length) {
			// The marker id already added.
			map.removeOverlay(gNumericMarkers[row_index - 1]);
			gNumericMarkers[row_index - 1] = new_marker;
		} else {
			gNumericMarkers.push(new_marker);
		}

		map.addOverlay(new_marker);
		gCurrentPoint = point;

		if (row_index == 1) {
			map.panTo(point);
		}
	}
}


function finish_numeric_polygon() {
	// Clear polygons first
	clear_polygon();

	var aDiv = $("numeric_polygon_popup_body");
	var tables = aDiv.getElementsByTagName("TABLE");

	for (var i = 0; i < tables.length; i++) {
		var table = $("ptb_" + i);
		var trs = table.getElementsByTagName("TR");
		var poly_points = [];

		for (j = 0; j < trs.length; j++) {
			row_index = j + 1;

			var lon = $("ptb_" + i + "_lon_" + row_index).value;
			var lat = $("ptb_" + i + "_lat_" + row_index).value;

			if (!isNaN(parseFloat(lon)) && !isNaN(parseFloat(lat))) {
				var point = new GLatLng(parseFloat(lat), parseFloat(lon));
				poly_points.push(point);
			}
		}

		if (poly_points.length <= 2) {
			alert("A polygon needs at least three points.");
			return false;
		}

		// If the first point is not the same as the last point, add a new point
		// to close the polygon.
		if (poly_points[0] != poly_points[poly_points.length - 1]) {
			var point = new GLatLng(poly_points[0].lat(), poly_points[0].lng());
			poly_points.push(point);
		}
		make_polygon(poly_points);
	}

	// Clear temporal markers.
	for (i = 0; i < gNumericMarkers.length; i++) {
		map.removeOverlay(gNumericMarkers[i]);
	}
	gNumericMarkers = [];
}


/***** Remove polygon *****/
function activate_remove_polygon() {
	var tool_type = "remove_polygon";
	var theTool = $("tool_" + tool_type);

	// Activate
	if (active_tool()  != tool_type) {
		// Deactivate the currently selected tool first.
		deactivate(active_tool());

		theTool.src='skins/icons/icon_tool_' + tool_type + '_selected.png'
		gToolStack.push(tool_type);
	}  else if (active_tool()  == tool_type) {
		deactivate_remove_polygon();
	}
}

function deactivate_remove_polygon() {
	var tool_type = "remove_polygon";
	var theTool = $("tool_" + tool_type);
	theTool.src='skins/icons/icon_tool_' + tool_type + '.png'
	gToolStack.pop();
}

/***** Zoom to Full Extent Tool *****/
function zoom_to_full_extent() {
	map.setCenter(gFullExtent.getCenter(), gZoomLevel);
}


/***** Recenter *****/
function activate_recenter() {
	theTool = $("tool_recenter");

	if (active_tool()  != "recenter") {
		theTool.src='skins/icons/icon_tool_recenter_selected.png';
		gToolStack.push("recenter");
		gRecenterClickHandler = GEvent.addListener(map, "click", recenter);
	} else if (active_tool()  == "recenter") {
		theTool.src='skins/icons/icon_tool_recenter.png';
		gToolStack.pop();
		GEvent.removeListener(gRecenterClickHandler);
	}
}

function recenter(marker, point) {
	if (active_tool()  != "recenter") {
		return false;
	}

	map.setCenter(point);

	// Deactivate itself
	GEvent.removeListener(gRecenterClickHandler);
	theTool = getObject("tool_recenter");
	theTool.src='skins/icons/icon_tool_recenter.png';
	gToolStack.pop();
}


/***** Zoom in to a rectangle *****/
function activate_zoomin() {
	theTool = $("tool_zoomin");

	if (active_tool()  != "zoomin") {
		// Deactivate other tool
		deactivate(active_tool());
		// Activate
		theTool.src='skins/icons/icon_tool_zoomin_selected.png';
		gToolStack.push("zoomin");
		gDistanceClickHandler = GEvent.addListener(map, "click", initializeLineDrawing);
	} else if (active_tool()  == "zoomin") {
		deactivate_zoomin();
	}
}

function deactivate_zoomin() {
	// Deactivate
	theTool = $("tool_zoomin");
	distance_clear();
	theTool.src='skins/icons/icon_tool_zoomin.png';
	gToolStack.pop();
	GEvent.removeListener(gDistanceClickHandler);
}

/***** Zoom in to a rectangle end *****/


/***** Polygon utilities *****/
/*
function identify_polygon(point) {
	for (var i=0; i< gPolygons.length; i++) {
		if (gPolygons[i].Contains(point)) {
		    return gPolygons[i];
		}
	}

	return false;		// No polygon found at the clicked point.
}
*/

/***** zoom_to_bounding_box_popup *****/
function show_zoom_to_bounding_box_popup() {
	$('zoom_to_popup').show();
}

function zoom_to_bounding_box() {
	if (parseFloat($F('bounding_latmax')) &&
		parseFloat($F('bounding_lonmin')) &&
		parseFloat($F('bounding_lonmax')) &&
		parseFloat($F('bounding_latmin'))
	) {
		var bounds = new GLatLngBounds(new GLatLng(parseFloat($F('bounding_latmin')), parseFloat($F('bounding_lonmin'))),
				new GLatLng(parseFloat($F('bounding_latmax')), parseFloat($F('bounding_lonmax'))));
		var center = bounds.getCenter();
		map.setCenter(center);
		map.setZoom(map.getBoundsZoomLevel(bounds));
	} else if (parseFloat($F('centerat_lon')) && parseFloat($F('centerat_lat'))) {
		map.setCenter(new GLatLng(parseFloat($F('centerat_lat')), parseFloat($F('centerat_lon'))));
	} else {
		alert ("Please enter latitude/longitude in decimal degree.");
	}
}