// #############################3
// #    map.js
// #############################3


var map;
var theAddMarker;
//var serverContent; // filled before loading by a (JSON) script
var editable = false;
var kilometerpaaltjes;

function startMap(mapid, owner) {
	// if owner, then allow editing of map
	editable = !!owner;
	
	//GLog.write("Opening map in "+(editable?"edit":"read-only")+" mode");
	
  if (GBrowserIsCompatible()) {
    map = new GMap2(document.getElementById(mapid), { draggableCursor: "default" });
		map.setCenter(new GLatLng(51.506151485557524, 5.3142499923706055), 15);

		// Enable the large zoom control left
		map.addControl(new GLargeMapControl3D());
		// Add the lower-left scale indicator
		map.addControl(new GScaleControl());
		// Enable double click for zoom
		map.enableDoubleClickZoom();
		// Enable wheel zoom
		map.enableScrollWheelZoom();
		// Map type buttons in the top right corner
		map.addControl(new GMapTypeControl());
		// Small minimap in the bottom right corner
		//map.addControl(new GOverviewMapControl(new GSize(150,150)));
	}
	
	if (serverContent) {
		var bounds = new GLatLngBounds();
		var latlngs = [];

		if (!kilometerpaaltjes) kilometerpaaltjes = [];

		var len = 0;
		var lastkm = 0;
		var lastlatlng;
		for (var i=0; i<serverContent.length; ++i) {
			var latlng = new GLatLng(serverContent[i].floatLat, serverContent[i].floatLon);
			bounds.extend(latlng);
			latlngs.push(latlng);
			
			if (i > 0) {
				len += lastlatlng.distanceFrom(latlng);

				while (Math.floor(len/1000) > lastkm) {
					++lastkm;
	
					var options 						= {};
					var icon                = new GIcon();
					icon.image 				= "images/maps/"+lastkm+".png";
					icon.iconSize           = new GSize(24, 24);
					icon.iconAnchor         = new GPoint(12, 12);
					icon.infoWindowAnchor   = new GPoint(12, 12);
					icon.shadow             = '';
					icon.shadowSize         = null;
					options.icon 						= icon;
				
					
					var dinges = (lastlatlng.distanceFrom(latlng) - (len-(lastkm*1000))) / lastlatlng.distanceFrom(latlng);
					// kmpaaltje op zoveelste van de lijn
					var kmp = new GMarker(
						new GLatLng(
							lastlatlng.lat()+((latlng.lat()-lastlatlng.lat())*dinges),
							lastlatlng.lng()+((latlng.lng()-lastlatlng.lng())*dinges)
						),
						options
					);
					//GLog.write(Math.floor(len/1000)+" "+lastkm+" "+kmp.getLatLng()+" "+icon.image);
					if (map) map.addOverlay(kmp);
					kilometerpaaltjes.push(kmp);
				}

			}	
			lastlatlng = latlng;		
		}
		addMarker(new GLatLng(serverContent[0].floatLat, serverContent[0].floatLon), null, 0, serverContent[0].strDesc);
		addMarker(new GLatLng(serverContent[serverContent.length-1].floatLat, serverContent[serverContent.length-1].floatLon), null, 1, serverContent[serverContent.length-1].strDesc);
		map.addOverlay(createPolyline(latlngs));
		if (bounds) map.setCenter(bounds.getCenter(), map.getBoundsZoomLevel(bounds));
	}
}

function iconMenuClick() {

}

function getSelectedIconIndex() {
	var els = document.getElementsByName('markertype');
	for (var i=0; i<els.length; ++i) {
		if (els[i].checked) return i;
	}
	// none selected, default to first
	return 0;
}


// #############################3
// #    htmlcontrol.js
// #############################3

// Always load this script after loading the Google Maps API!

/**
 * Constructor to create a new control
 * map = GMap2 object
 * styles = (optional) associative array equal to element.style
 * str = (optional) div.innerHTML is set to str
 */
function HTMLControl(map, styles, str) {
	if (!styles) styles = {};
	this._div = document.createElement("div");
	if (str) this._div.innerHTML = str;
	var ds = this._div.style;
	ds.position = "absolute";
	// set styles as given
	for (n in styles) {
		ds[n] = styles[n];
	}
};
HTMLControl.prototype = new GControl(true, true);
HTMLControl.prototype.initialize = function(map) { 
	map.getContainer().appendChild(this._div);
	return this._div; 
};
HTMLControl.prototype.printable = function() { return true; };
HTMLControl.prototype.selectable = function() { return true; };
HTMLControl.prototype.getDefaultPosition = function() { return null; }; // does not seem to matter
/**
 * Change the innerHTML and optionally set the left and top styles (those are numbers, not strings)
 */
HTMLControl.prototype.setInnerHTML = function(str, left, top) { 
	this._div.innerHTML = str;
	if (top) this._div.style.top = top+"px";
	if (left) this._div.style.left = left+"px";
};

// #############################3
// #    track.js
// #############################3

var track = [];

var intMinMouseLineDistance = 50;
var intMaxMousePointDistance = 20;

// track markers
var iconImagesTrack = [
	{url: 'images/maps/start.png'},
	{url: 'images/maps/einde.png'}
];

// internal markers
var iconImagesInternal = {
	addmarker: {url: 'images/map/dots/reddot.gif',    desc: 'Klik hier om een nieuwe marker toe te voegen'}
};

function addMarker(latlng, index, iconIndexOverride, desc) {
	if (typeof(index) != 'number') index = -1;

	var marker = createMarker(latlng, (iconIndexOverride?iconIndexOverride:getSelectedIconIndex()), {draggable: editable});
	
	marker.XXdescription = desc;
	
	if (index >= 0 && index < track.length) {
		track.splice(index, 0, marker);
	}
	else {
		index = track.length;
		track.push(marker);
	}
	showMarker(null, index);
	
	if (editable) updateTrackLength();
	if (editable) addTrackToForm();
}

function createMarkerObj(latlng, iconindex, options) {
	if (!options) options = {};

	var icon                = new GIcon();
	if (typeof(iconindex) == 'string')      icon.image = iconImagesInternal[iconindex].url;
	else if (typeof(iconindex) == 'number') icon.image = iconImagesTrack[iconindex].url;
	else icon.image         = 'images/map/dots/greendot.gif'; // should never happen though
	icon.iconSize           = new GSize(24, 24);
	icon.iconAnchor         = new GPoint(12, 12);
	icon.infoWindowAnchor   = new GPoint(12, 12);
	icon.shadow             = '';
	icon.shadowSize         = null;
	options.icon = icon;

	var marker = new GMarker(latlng, options);
	
	// save the marker image
	marker.XXiconIndex = iconindex;
	
	return marker;
}

function createMarker(latlng, iconindex, options) {
	var marker = createMarkerObj(latlng, iconindex, options);
	
	if (editable) {
		GEvent.addListener(marker, "click", function () {
			// we dont know the current index of this marker,
			// but the marker reference will be known to this
			// function so we can call getMarkerIndex on it
			// at runtime to get the correct index for it.
			var markerindex = getMarkerIndex(marker);
	
			// iconImagesTrack contains all the possible marker urls and their desc
			var iconmenu = "<div>Selecteer icoon voor dit punt:</div>";
			for (var i=0; i<iconImagesTrack.length; ++i) {
				iconmenu += 
					"<div style='float: left; text-align: center;' onclick='changeMarkerIcon("+markerindex+", "+i+");'>"+
						"<img src='"+iconImagesTrack[i].url+"' style='vertical-align: middle; text-align: center;' /><br />"+
						"<input type='radio' name='changeicon' "+(marker.XXiconIndex==i?'checked ':'')+"/><br />"+
					"</div>";
			}
	
			var delmenu = 
				"Wil je dit punt verwijderen?<br />"+
				"<a href='javascript:removeMarker(null, "+markerindex+");'>ja</a>";
			
			var descmenu = "Omschrijving (max 1000 tekens):<br /><textarea id='desc"+markerindex+"' onchange='editDescription("+markerindex+", this.value);' style='width: 200px; height: 75px;'>"+marker.XXdescription+"</textarea>";
	
			// show popup
			marker.openInfoWindowHtml(marker.getLatLng().lat()+" "+marker.getLatLng().lng()+"<br />"+iconmenu+"<br /><br /><br />"+delmenu+"<br /><br />"+descmenu+"<br /><br />&nbsp;&nbsp;&nbsp;<a href='javascript:track["+markerindex+"].closeInfoWindow();'>sluit venster</a>");
		});
	}
	else {
		GEvent.addListener(marker, "click", function () {
			if (marker.XXdescription && marker.XXdescription.length > 0) {
				marker.openInfoWindowHtml(marker.XXdescription);
			}
		});
	}

	GEvent.addListener(marker, "drag", function() {
		updateMarker(marker, false, true);
		updateTrackLength();
		addTrackToForm();
	});
	return marker;
}

function editDescription(index, desc) {
	track[index].XXdescription = desc;
}

function showMarker(marker, index) {
	if (!marker) marker = track[index];
	else index = getMarkerIndex(marker);

	map.addOverlay(marker);
}



function createPolyline(arrLatLng) {
	if (arrLatLng) return new GPolyline(arrLatLng, 'blue', 2, 1);
	return null;
}

function removeMarker(marker, index) {
	if (!marker) marker = track[index];
	else index = getMarkerIndex(marker);

	if (index >= track.length) {
		GLog.write("bounds error");
	}
	else if (index == 0) {
		map.removeOverlay(track.shift());
		if (track.length >= 1) {
			updateMarker(null, 0);
		}
	}
	else if (index == track.length-1) {
		map.removeOverlay(track.pop());
		updateMarker(null, track.length-1);
	}
	else {
		map.removeOverlay(track.splice(index, 1)[0]);
		updateMarker(null, index-1);
		updateMarker(null, index);
	}
	
	updateTrackLength();
	addTrackToForm();
}

function getMarkerIndex(marker) {
	for (var i=0; i<track.length; ++i) {
		if (track[i] == marker) {
			return i;
		}
	}
}

function showNearestLineAddMarker(latlng) {
	var C = map.fromLatLngToContainerPixel(latlng);
	var E; // yeah, capital E!
	var floatLowLen;
	var intMinIndex;
	var boolFirstLine = true;
	var closestpoint;
	var closestindex;
	
	var len = track.length;
	
	if (len > 1) { // no point in adding a line when you only have a point :)
		for (var i=1; i<len; ++i) {
			// get our points (as x,y coordinates to the div...)
			var A = map.fromLatLngToContainerPixel(new GLatLng(track[i-1].getLatLng().lat(), track[i-1].getLatLng().lng()));
			var B = map.fromLatLngToContainerPixel(new GLatLng(track[i].getLatLng().lat(), track[i].getLatLng().lng()));
			
			// compute D
			var top = ((C.x-A.x)*(B.x-A.x)) + ((C.y-A.y)*(B.y-A.y));
			var bottom = Math.pow(B.x - A.x, 2) + Math.pow(B.y - A.y, 2);
			var u = top / bottom;
			
			var D;
			if (u < 0) D = A;
			else if (u > 1) D = B;
			else D = new GPoint( A.x + (u * (B.x - A.x)), A.y + (u * (B.y - A.y)) );
			
			var distance = Math.sqrt(Math.pow(C.x - D.x, 2) + Math.pow(C.y - D.y, 2));
			if (boolFirstLine || distance < floatLowLen) {
				floatLowLen = distance;
				if (u > 0 && u < 1) E = D;
				else E = null;
				closestpoint = (u < 0.5 ? A : B);
				boolFirstLine = false;
				closestindex = i;
			}
		}

		var EtoD = (E?Math.sqrt(Math.pow(E.x - closestpoint.x, 2) + Math.pow(E.y - closestpoint.y, 2)):0);
		if (E && floatLowLen < intMinMouseLineDistance && E != closestpoint && EtoD > intMaxMousePointDistance) {
			var targetGLatLng = map.fromContainerPixelToLatLng(E);
			if (!theAddMarker) {
				createTheAddMarker(targetGLatLng);
				map.addOverlay(theAddMarker);
			}
			else {
				theAddMarker.setLatLng(targetGLatLng);
				if (theAddMarker.isHidden()) theAddMarker.show();
			}
			theAddMarker.XXpoint1 = track[closestindex-1];
			theAddMarker.XXpoint2 = track[closestindex];
		}
		else {
			if (theAddMarker) theAddMarker.hide();
		}
	}
	else { // 0 or 1 point in array
		if (theAddMarker) theAddMarker.hide();
	}
}

function createTheAddMarker(latlng) {
	theAddMarker = createMarkerObj(latlng, 'addmarker', {draggable: false});
	GEvent.addListener(theAddMarker, "click", function () {
		addMarker(theAddMarker.getLatLng(), getMarkerIndex(theAddMarker.XXpoint2));
	});
}

function changeMarkerIcon(markerindex, iconindex) {
	var marker = track[markerindex];
	marker.setImage(iconImagesTrack[iconindex].url);
	marker.XXiconIndex = iconindex;
}



