function padLeft(ostr, len, chr) {
	str = ostr;
	while (str.length < len)
		str = chr + str;
	
	return str;
}
function clearDebug() {
	if (db = document.getElementById("debug"))
		db.value = "";
}
function debug(msg) {
	if (db = document.getElementById("debug")) {
		d = new Date();
		db.value = "[" + padLeft(d.getHours().toString(), 2, "0") + ":" + padLeft(d.getMinutes().toString(), 2, "0") + ":" + padLeft(d.getSeconds().toString(), 2, "0") + "." + padLeft(d.getMilliseconds().toString(), 3, "0") + "] " + msg + "\n" + db.value;
	}
}

function Map(points, options) {
	this.points = points;		// the array of points as defined in map_json.tpl.  This needs to be in ascending chronological order.

	np = this.points.length;

	while (np > 0 && !thePoints[np])
		np--;	// IE no-last-element bug (or security feature)

	this.numPoints = np + 1;
	
	this.colours = new Array("#000000", "#FF6600", "#0000ff", "#ff0000", "#ff00ff");

	// There will be a single marker for every Location.  Multiple DailyRecord points may
	// be enclosed within a single marker.
	//
	// Markers are stored in this object, which uses Location ID as its lookup.
	this.markers = {};

	// There will be a line in between each DailyRecord point.  These are just indexed
	// incrementally, i.e. Line 1 is between Point 1 and Point 2, Line 2 is between
	// Point 2 and Point 3, etc.
	this.lines = [];

	if (!options)
		options = {};

	if (!options.latlng)
		options.latlng = new GLatLng(50.6421, 2.64359);		// 50.6421, 2.64359
	
	if (!options.zoom)
		this.zoom = 9;
	else
		this.zoom = options.zoom;
	
	if (options.hideInfoWindows)
		this.showInfoWindows = false;
	else
		this.showInfoWindows = true;
	
	if (options.autoResize)
		this.autoResize = true;
	else
		this.autoResize = false;
	
	if (GBrowserIsCompatible()) {
		this.map = new GMap2(document.getElementById("map"));
		
		this.map.setCenter(options.latlng, this.zoom);
		
		this.map.enableDoubleClickZoom();
		this.map.enableContinuousZoom();
	}
}

Map.prototype.showPoints = function(startDate, endDate) {
	// display points from the map
	if (!startDate && !endDate) {
		startDate = '1800-01-01 00:00:00';
		endDate = '2100-01-01 00:00:00';
	} else if (!endDate) {
		// If only one date argument is present, we display points from the beginning to that date.
		endDate = startDate;
		startDate = '1800-01-01 00:00:00';
	}

	if (startDate.length < 11)
		startDate += " 00:00:00";
	if (endDate.length < 11)
		endDate += " 23:59:59";
	
	var totalLat = totalLng = numPoints = 0;
	
	for (i=0; i < this.numPoints; i++) {
		if (this.points[i] && this.points[i].date >= startDate && this.points[i].date <= endDate) {			
			numPoints++;
			
			totalLat += this.points[i].lat;
			totalLng += this.points[i].lng;
			
			if (this.markers[this.points[i].location.id] || this.lines[i]) {
				/* If we already have the lines and points in the arrays, just re-add them instead of re-calculating everything.
				 */
				if (this.markers[this.points[i].location.id])
					this.map.addOverlay(this.markers[this.points[i].location.id]);
				if (this.lines[i])
					this.map.addOverlay(this.lines[i]);
			} else {
			
				// SO: What we have to do here is to change the markers[] array from being based on POINTS (daily_record) to being
				// based on LOCATIONS.  Multiple points can be enclosed within a single location marker.  These will be separated
				// by tabs.
				
				/* First time through the points:  calculate all the stuff we need.
				 */
				var spot = new GLatLng(this.points[i].location.lat, this.points[i].location.lng);

				// This is where it gets annoying.  We have to loop through the points to find all the other points
				// with this Location, and add them to the tabbed overlay.
				if (this.showInfoWindows) {
					var marker = new GMarker(spot);
					
					var locationID = this.points[i].location.id;
					var numPointsForThisLocation = 0;
					var pointsForThisLocation = [];
					
					for (k=0; k < this.numPoints; k++) {
						if (this.points[k].location.id == locationID) {
							var numLetters = this.points[k].letters.length;
							if (numLetters > 0) {
								pointsForThisLocation[numPointsForThisLocation++] = new GInfoWindowTab(this.points[k].letters[0].date_written, createInfoPanel(this.points[k]));
							}
						}
					}				
					
					if (numPointsForThisLocation > 0) {
						marker.bindInfoWindowTabs(pointsForThisLocation);
						this.markers[this.points[i].location.id] = marker;
						this.map.addOverlay(marker);								
					}
				} else {
					// Just display a simple marker.
					var marker = new GMarker(spot);
					this.markers[this.points[i].location.id] = marker;
					this.map.addOverlay(marker);													
				}

				if (i > 0 && this.points[i-1].date >= startDate) {
					// plot a line from last point to this point
					var oldSpot = new GLatLng(this.points[i-1].location.lat, this.points[i-1].location.lng);
					var line = new GPolyline([oldSpot, spot], this.colours[this.points[i].transport.id], 6);
					this.lines[i] = line;
					this.map.addOverlay(line);
				}
			}
		}
	}
	
	if (numPoints < 60 && this.autoResize) {
		centreLat = totalLat / numPoints;
		centreLng = totalLng / numPoints;
		
		this.map.setCenter(new GLatLng(centreLat,centreLng));		
	}	
}

Map.prototype.hidePoints = function(startDate, endDate) {
	// remove points from the map

	if (!startDate && !endDate) {
		startDate = '1800-01-01 00:00:00';
		endDate = '2100-01-01 00:00:00';
	} else if (!endDate) {
		// If only one date argument is present, we hide points from the beginning to that date.
		endDate = startDate;
		startDate = '1800-01-01 00:00:00';
	}
	
	if (startDate.length < 11)
		startDate += " 00:00:00";
	if (endDate.length < 11)
		endDate += " 23:59:59";
	
	for (i=0; i < this.numPoints; i++) {
		if (this.points[i].date >= startDate && this.points[i].date <= endDate) {
			if (this.markers[this.points[i].location.id])
				this.map.removeOverlay(this.markers[this.points[i].location.id]);
			if (this.lines[i])
				this.map.removeOverlay(this.lines[i]);				
		}
	}
}

function primitiveElement(type, content) {
	var elm = document.createElement(type);
	elm.innerHTML = content;
	return elm;
}

function createInfoPanel(point) {
	var h2 = primitiveElement("h2", point.location.name);
	var h3 = primitiveElement("h3", point.date.slice(0,10));
	var ul = document.createElement("ul");
	
	if (point.role.id) {
		var li = document.createElement("li");
		li.innerHTML = __("Battalion Role") + ": " + point.role.name;
		ul.appendChild(li);
	}
	if (point.transport.id) {
		var li = document.createElement("li");
		li.innerHTML = __("Mode of Transport") + ": " + point.transport.name;
		ul.appendChild(li);
	}
	
	if (point.letters.length > 0) {
		for(j=0; point.letters[j]; j++) {
			var li = document.createElement("li");
			li.innerHTML = "&#187; ";
			var a = document.createElement("a");
			a.href = "/letters/index.php?id=" + point.letters[j].id;
			a.innerHTML = __("Letter of") + " " + point.letters[j].date_written;

			li.appendChild(a);
			ul.appendChild(li);
		}
	}

	if (point.warDiaries.length > 0) {
		for(j=0; point.warDiaries[j]; j++) {
			var li = document.createElement("li");
			li.innerHTML = "&#187; ";
			var a = document.createElement("a");
			a.href = "/view/index.php?id=" + point.warDiaries[j].id;
			a.innerHTML = __("War Diary") + ": " + " " + point.warDiaries[j].date_to + " &ndash; " + point.warDiaries[j].date_from;

			li.appendChild(a);
			ul.appendChild(li);						
		}
	}
	if (point.battalionOrders.length > 0) {
		for(j=0; point.battalionOrders[j]; j++) {
			var li = document.createElement("li");
			li.innerHTML = "&#187; ";
			var a = document.createElement("a");
			a.href = "/view/index.php?id=" + point.battalionOrders[j].id;
			a.innerHTML = __("Order") + ": " + point.battalionOrders[j].date_to + " &ndash; " + point.battalionOrders[j].date_from;

			li.appendChild(a);
			ul.appendChild(li);						
		}					
	}

	var wrap = document.createElement("div");
	wrap.appendChild(h2);
	wrap.appendChild(h3);
	wrap.appendChild(ul);
	
	return wrap;
}

