var mapdiv = document.getElementById("map");
var map;
var poly;
var points = new Array();
var markers = new Array();
var milemarkers = new Array();
var tooltip;
var lineColor = "#151B8D";
var lineWeight = 4;
var lineOpacity = .7;
var report = document.getElementById("status");
var geocoder = null;
var bounds = null;
var MILES = "0";
var KILOMETERS = "1";
var fejlPoints;

var markersOn = true;
var centerOn = true;
var roadsOn = false;


function toggleMarkers() {
	markersOn = document.controlPanel.markers.checked;
	drawOverlay(true);
}

function toggleFollowRoads() {
	roadsOn = document.controlPanel.roads.checked;
}

function toggleCenter() {
	centerOn = document.controlPanel.center.checked;
}
function setMapSize(){
	var myWidth=0,myHeight=0;
	if(typeof(window.innerWidth)=='number'){
		myWidth=window.innerWidth;
		myHeight=window.innerHeight;
	} else if(document.documentElement&&(document.documentElement.clientWidth||document.documentElement.clientHeight)){
		myWidth=document.documentElement.clientWidth;
		myHeight=document.documentElement.clientHeight;
	}else if(document.body&&(document.body.clientWidth||document.body.clientHeight)){myWidth=document.body.clientWidth;
		myHeight=document.body.clientHeight;
	}
	document.getElementById("map").style.height=(myHeight-95)+"px";
}

function gemRute(updater){
	points.length = 0;
	for(i = 0; i < markers.length; i++) {
		points.push(markers[i].getLatLng());
	}
	polylineEncoder = new PolylineEncoder();
	polyline = polylineEncoder.dpEncode(points);
	var url = '/index.php?option=com_routes'
		+ '&Itemid=41'
		+ '&centerX=' + escape(bounds.getCenter().lng())
		+ '&centerY=' + escape(bounds.getCenter().lat())
		+ '&zl=' + new String(map.getBoundsZoomLevel(bounds)-1)
		+ '&distance=' + afstandIValgteEnhed().toFixed(2)
		+ '&version=2'
		+ '&multiplier=' + getCurrentMultiplier()
		+ '&polyline=' + polyline.encodedPoints
		+ '&levels=' + polyline.encodedLevels
		;
	if(route_code.length > 0 && updater) {
		url = url + "&code=" + route_code;
		url = url + '&task=updateroutepolyline';
	} else {
		url = url + '&task=nameroute';
	}
	location.href= url;
}

function addMileMarkers() {
	var totaldist = 0;
	var sidsteMilMarker = 0;
	var begyndelsesAfstand = 0;
	var totalDistance = afstandIValgteEnhed();
	if(totalDistance >= 30) {
		var increment = 5;
	} else if(totalDistance >= 16) {
		var increment = 2;
	} else {
		var increment = 1;
	}
	for (var i=1; i < (markers.length); i++)
	{
		var legdistance = (markers[i-1].getLatLng().distanceFrom(markers[i].getLatLng()) / 1000.0 * getCurrentMultiplier());
		var afstandTilNaesteMarker = Math.ceil(totaldist/increment)*increment - totaldist;
		begyndelsesAfstand = Math.floor(totaldist+legdistance);
		if (afstandTilNaesteMarker == 0) {
			afstandTilNaesteMarker += increment;
		}
		while ((afstandTilNaesteMarker < (totaldist + legdistance)) && ((totaldist + afstandTilNaesteMarker) < (totaldist + legdistance)) && (sidsteMilMarker < 101)) {
			if(begyndelsesAfstand >= sidsteMilMarker+increment) {
				sidsteMilMarker += increment;
				mileMarker(afstandTilNaesteMarker, legdistance, markers[i-1].getLatLng(), markers[i].getLatLng(), sidsteMilMarker);
			}
			afstandTilNaesteMarker += increment;
		}
		totaldist += legdistance;
	}
}
function mileMarker(distToNextMarker, legDistance, point1, point2, sidsteMilMarker) {
xy = (distToNextMarker/legDistance) * afstandMellemPunkter(point1,point2);
kx = xy * (1 / Math.sqrt(1 + Math.pow(slope(point1,point2),2)));
ky = xy * (slope(point1,point2) / Math.sqrt(1 + Math.pow(slope(point1,point2),2) ));
if (parseFloat(point1.x) > parseFloat(point2.x)) {
kx = -kx;
ky = -ky;
}
nx = parseFloat(point1.x) + kx;
ny = parseFloat(point1.y) + ky;
try {
if (sidsteMilMarker < 101) {
var icon = new GIcon();
icon.image = "http://www.logyourrun.com/images/M_images/map_pointer"+sidsteMilMarker+".png";
icon.shadow = "http://www.logyourrun.com/images/M_images/map_pointer_shadow.png";
icon.iconSize = new GSize(13, 20);
icon.shadowSize = new GSize(13, 20);
icon.iconAnchor = new GPoint(7, 20);
icon.infoWindowAnchor = new GPoint(1, 7);
newpoint = new GLatLng(ny, nx);
var milemarker = new GMarker(newpoint, {icon:icon, draggable:false, bouncy:false, dragCrossMove:false});
map.addOverlay(milemarker);
milemarkers.push(milemarker);
}
}
catch(ex) {
}
}
function afstandMellemPunkter(point1,point2) {
var x2 = Math.abs(point2.x - point1.x) * Math.sqrt(Math.pow(slope(point1,point2),2)+1);
return x2;
}
function slope(point1, point2) {
return (point1.y - point2.y) / (point1.x - point2.x);
}	
function getCurrentMultiplier(){
var unitInput = document.controlPanel.units;
var curValue;
if (unitInput.value == 101) {
curValue = KILOMETERS;
} else if (unitInput.value == 100) {
curValue = MILES;
} else if (unitInput[0].checked) {
curValue = MILES;
} else if (unitInput[1].checked) {
curValue = KILOMETERS;
}
var multiplier;
if (curValue==KILOMETERS) {
multiplier = 1.0;
} else {
multiplier = 0.621371192;
}
return multiplier;
}
function afstandIValgteEnhed(){
return poly.getLength() / 1000 * getCurrentMultiplier();
}
function nyeEnheder() {
drawOverlay(true);
}
function showAddress(address) {
	if (geocoder) {
    geocoder.getLatLng(
     address,
     function(point) {
       if (!point) {
         alert(address + " not found");
       } else {
         map.setCenter(point, 13);
         var marker = new GMarker(point);
         map.addOverlay(marker);
         marker.openInfoWindowHtml(address);
       }
     });
  }
}

function fjernSidsteEtappe() {
	if (markers.length > 0 && fejlPoints > 1) {
		for (var i=0; i < fejlPoints; i++) {
			map.removeOverlay(markers[markers.length-1]);
			markers.pop();
		}
		drawOverlay(true);
	
	} else if (markers.length > 0) { 
		map.removeOverlay(markers[markers.length-1]);
		markers.pop();
		drawOverlay(true);
	} else {
		alert('No points to remove');
	}
	fejlPoints=1;
}

function fremOgTilbage(){
	var mid = markers.length - 1;

	if (markers.length > 1) {
		for (var i= mid-1; i >= 0; i--) {
			addPoint(markers[i].getLatLng());
		}
		drawOverlay(true);		
	}
}
function showTooltip(marker) {
 tooltip.innerHTML = "Click to remove<br>Drag to move";
 tooltip.style.display = "block";
 if(typeof(tooltip.style.filter) == "string") {
	 tooltip.style.filter = "alpha(opacity:70)";
 }
 var currtype = map.getCurrentMapType().getProjection();
 var point    = currtype.fromLatLngToPixel(map.fromDivPixelToLatLng(new GPoint(0,0),true),map.getZoom());
 var offset   = currtype.fromLatLngToPixel(marker.getLatLng(),map.getZoom());
 var anchor   = marker.getIcon().iconAnchor;
 var width    = marker.getIcon().iconSize.width + 6;
 var height   = 10;
 var pos      = new GControlPosition(G_ANCHOR_TOP_LEFT, new GSize(offset.x - point.x - anchor.x + width, offset.y - point.y -anchor.y - height)); 
 pos.apply(tooltip);
}


function initializeMap() {
	if (!GBrowserIsCompatible()) {
    alert('Your browser is not compatible with the Google Maps API');
    return;
  }
  var polyline = "";
	geocoder = new GClientGeocoder();
	bounds = new GLatLngBounds;
	map = new GMap2(mapdiv, {draggableCursor:"crosshair", draggingCursor:"move"});
 	tooltip = document.createElement("div");
 	tooltip.className="tooltip";
 	map.getPane(G_MAP_MARKER_PANE).appendChild(tooltip);
 	map.setCenter(new GLatLng(52.05249,9.84375), 12);
 	map.addControl(new GLargeMapControl());
 	map.addMapType(G_PHYSICAL_MAP);
 	var hierarchy = new GHierarchicalMapTypeControl();
 	hierarchy.addRelationship(G_SATELLITE_MAP, G_HYBRID_MAP, "Hybrid", true);
 	map.addControl(hierarchy);
 	map.addControl(new GScaleControl());
 	map.disableDoubleClickZoom();
	if(route_centerX) {
		var curCenterX = route_centerX;
		var curCenterY = route_centerY;
		var zoomLevel = route_zoom;
		var levels = route_levels;
	}
	if (route_polyline.length > 0 && route_centerX) {
		decodeLine(route_polyline);
		map.setZoom(map.getBoundsZoomLevel(bounds)-1);
		map.setCenter(bounds.getCenter());
		GEvent.addListener(map, "click", leftClick);
	} else {
		map.setCenter(new GLatLng(curCenterY, curCenterX), zoomLevel);
		GEvent.addListener(map, "click", leftClick);
	}
}

function leftClick(overlay, latlng) {
	var point = new GLatLng( latlng.lat(), latlng.lng() );
	
	if(point) {
	
		if (roadsOn) {
		
			var directions = new GDirections(null,document.getElementById("hidden_div"));

			GEvent.addListener(directions,"load",function(){
				if(directions.getNumRoutes()>0){
					// got directions
				
					fejlPoints=0;
					var GPolyline = directions.getPolyline();
					var intVertexCount=GPolyline.getVertexCount();
					var OldPoint=markers[markers.length-1].getLatLng();
				
					for(var i=0;i<intVertexCount;i++){
						var cPoint = GPolyline.getVertex(i);
						if(cPoint.equals(OldPoint)===false){
							addPoint(cPoint);
							fejlPoints++;
						} 
						OldPoint=cPoint;
					}

				} else{
					// no directions necessary (straight line)
					addPoint(point);
					fejlPoints=1;
				}
				drawOverlay(true);
			});
	
			var da = new Array();
			if (markers.length > 0) {
				da[0] = markers[markers.length-1].getLatLng();
				da[1] = point;
				directions.loadFromWaypoints(da,{getPolyline:true,travelMode:G_TRAVEL_MODE_WALKING});
			} else {
				addPoint(point);
			}
			
		} else {
			addPoint(point);
			fejlPoints=1;
			drawOverlay(true);
		}
		
		if (centerOn) {
			map.setCenter(point);
		}
	}
}

function addPoint (point) {

		bounds.extend(point);
		var icon = new GIcon();
		icon.image = "http://www.logyourrun.com/images/editablepoint.png";
		icon.iconSize   = new GSize(12, 12);
		icon.iconAnchor = new GPoint(6, 6);
		var marker = new GMarker(point, {icon:icon, draggable:true, bouncy:false, dragCrossMove:true});
		map.addOverlay(marker);
		markers.push(marker);
		
		GEvent.addListener(marker, "mouseover", function() {
			showTooltip(marker);
		});
		GEvent.addListener(marker, "mouseout", function() {
			tooltip.style.display = "none";
		});
		GEvent.addListener(marker, "drag", function() {
			tooltip.style.display= "none";
			drawOverlay(false);
		});
		GEvent.addListener(marker, "mouseup", function() {
			tooltip.style.display= "none";
			drawOverlay(true);
		});
		GEvent.addListener(marker, "click", function() {
			tooltip.style.display = "none";
			for(var n = 0; n < markers.length; n++) {
				if(markers[n] == marker) {
					map.removeOverlay(markers[n]);
					break;
				}
			}
			markers.splice(n, 1);
			if(markers.length > 0) {
				drawOverlay(true);
			}
		});


}



function drawOverlay(showMarkers){
  if(poly) { 
    map.removeOverlay(poly); 
  }
  points.length = 0;

  for(i = 0; i < markers.length; i++) {
    points.push(markers[i].getLatLng());
  }
  poly = new GPolyline(points, lineColor, lineWeight, lineOpacity);
	var length = afstandIValgteEnhed();
  report.innerHTML = "Route length: " + length.toFixed(2);
  map.addOverlay(poly);
	if (showMarkers) {
	  for(i = 0; i < milemarkers.length; i++) {
	    map.removeOverlay(milemarkers[i]);
	  }
	  if (markersOn) {
			addMileMarkers();
		}
	}
}
function nyRute() {
map.clearOverlays();
points.length = 0;
markers.length = 0;
report.innerHTML = "&nbsp;";
}
function decodeLine (encoded) {
var len = encoded.length;
var index = 0;
var array = [];
var lat = 0;
var lng = 0;
while (index < len) {
var b;
var shift = 0;
var result = 0;
do {
b = encoded.charCodeAt(index++) - 63;
result |= (b & 0x1f) << shift;
shift += 5;
} while (b >= 0x20);
var dlat = ((result & 1) ? ~(result >> 1) : (result >> 1));
lat += dlat;
shift = 0;
result = 0;
do {
b = encoded.charCodeAt(index++) - 63;
result |= (b & 0x1f) << shift;
shift += 5;
} while (b >= 0x20);
var dlng = ((result & 1) ? ~(result >> 1) : (result >> 1));
lng += dlng;
newpoint = new GLatLng(lat * 1e-5, lng * 1e-5);
leftClick("", newpoint);
}}

PolylineEncoder = function(numLevels, zoomFactor, verySmall, forceEndpoints) {
var i;
if(!numLevels) {
numLevels = 18;
}
if(!zoomFactor) {
zoomFactor = 2;
}
if(!verySmall) {
verySmall = 0.00001;
}
if(!forceEndpoints) {
forceEndpoints = true;
}
this.numLevels = numLevels;
this.zoomFactor = zoomFactor;
this.verySmall = verySmall;
this.forceEndpoints = forceEndpoints;
this.zoomLevelBreaks = new Array(numLevels);
for(i = 0; i < numLevels; i++) {
this.zoomLevelBreaks[i] = verySmall*Math.pow(zoomFactor, numLevels-i-1);
}}
PolylineEncoder.prototype.dpEncode = function(points) {
var absMaxDist = 0;
var stack = [];
var dists = new Array(points.length);
var maxDist, maxLoc, temp, first, last, current;
var i, encodedPoints, encodedLevels;
var segmentLength;
if(points.length > 2) {
stack.push([0, points.length-1]);
while(stack.length > 0) {
current = stack.pop();
maxDist = 0;
segmentLength = Math.pow(points[current[1]].lat()-points[current[0]].lat(),2) + 
Math.pow(points[current[1]].lng()-points[current[0]].lng(),2);
for(i = current[0]+1; i < current[1]; i++) {
temp = this.distance(points[i],points[current[0]], points[current[1]],segmentLength);
if(temp > maxDist) {
maxDist = temp;
maxLoc = i;
if(maxDist > absMaxDist) {
absMaxDist = maxDist;
}}}
if(maxDist > this.verySmall) {
dists[maxLoc] = maxDist;
stack.push([current[0], maxLoc]);
stack.push([maxLoc, current[1]]);
}}}
  
  encodedPoints = this.createEncodings(points, dists);
  encodedLevels = this.encodeLevels(points, dists, absMaxDist);
  return {
    encodedPoints: encodedPoints,
    encodedLevels: encodedLevels,
    encodedPointsLiteral: encodedPoints.replace(/\\/g,"\\\\")
  }
}
PolylineEncoder.prototype.distance = function(p0, p1, p2, segLength) {
  var u, out;
  
  if(p1.lat() === p2.lat() && p1.lng() === p2.lng()) {
    out = Math.sqrt(Math.pow(p2.lat()-p0.lat(),2) + Math.pow(p2.lng()-p0.lng(),2));
  }
  else {
    u = ((p0.lat()-p1.lat())*(p2.lat()-p1.lat())+(p0.lng()-p1.lng())*(p2.lng()-p1.lng()))/
      segLength;
  
    if(u <= 0) {
      out = Math.sqrt(Math.pow(p0.lat() - p1.lat(),2) + Math.pow(p0.lng() - p1.lng(),2));
    }
    if(u >= 1) {
      out = Math.sqrt(Math.pow(p0.lat() - p2.lat(),2) + Math.pow(p0.lng() - p2.lng(),2));
    }
    if(0 < u && u < 1) {
      out = Math.sqrt(Math.pow(p0.lat()-p1.lat()-u*(p2.lat()-p1.lat()),2) +
        Math.pow(p0.lng()-p1.lng()-u*(p2.lng()-p1.lng()),2));
    }
  }
  return out;
}
PolylineEncoder.prototype.createEncodings = function(points, dists) {
  var i, dlat, dlng;
  var plat = 0;
  var plng = 0;
  var encoded_points = "";

  for(i = 0; i < points.length; i++) {
    if(dists[i] != undefined || i == 0 || i == points.length-1) {
      var point = points[i];
      var lat = point.lat();
      var lng = point.lng();
      var late5 = Math.floor(lat * 1e5);
      var lnge5 = Math.floor(lng * 1e5);
      dlat = late5 - plat;
      dlng = lnge5 - plng;
      plat = late5;
      plng = lnge5;
      encoded_points += this.encodeSignedNumber(dlat) + 
        this.encodeSignedNumber(dlng);
    }
  }
  return encoded_points;
}
PolylineEncoder.prototype.computeLevel = function(dd) {
  var lev;
  if(dd > this.verySmall) {
    lev=0;
    while(dd < this.zoomLevelBreaks[lev]) {
      lev++;
    }
    return lev;
  }
}
PolylineEncoder.prototype.encodeLevels = function(points, dists, absMaxDist) {
  var i;
  var encoded_levels = "";
  if(this.forceEndpoints) {
    encoded_levels += this.encodeNumber(this.numLevels-1)
  } else {
    encoded_levels += this.encodeNumber(
      this.numLevels-this.computeLevel(absMaxDist)-1)
  }
  for(i=1; i < points.length-1; i++) {
    if(dists[i] != undefined) {
      encoded_levels += this.encodeNumber(
        this.numLevels-this.computeLevel(dists[i])-1);
    }
  }
  if(this.forceEndpoints) {
    encoded_levels += this.encodeNumber(this.numLevels-1)
  } else {
    encoded_levels += this.encodeNumber(
      this.numLevels-this.computeLevel(absMaxDist)-1)
  }
  return encoded_levels;
}
PolylineEncoder.prototype.encodeNumber = function(num) {
  var encodeString = "";
  var nextValue, finalValue;
  while (num >= 0x20) {
    nextValue = (0x20 | (num & 0x1f)) + 63;
    encodeString += (String.fromCharCode(nextValue));
    num >>= 5;
  }
  finalValue = num + 63;
  encodeString += (String.fromCharCode(finalValue));
  return encodeString;
}
PolylineEncoder.prototype.encodeSignedNumber = function(num) {
  var sgn_num = num << 1;
  if (num < 0) {
    sgn_num = ~(sgn_num);
  }
  return(this.encodeNumber(sgn_num));
}
PolylineEncoder.latLng = function(y, x) {
	this.y = y;
	this.x = x;
}
PolylineEncoder.latLng.prototype.lat = function() {
	return this.y;
}
PolylineEncoder.latLng.prototype.lng = function() {
	return this.x;
}
PolylineEncoder.pointsToLatLngs = function(points) {
	var i, latLngs;
	latLngs = new Array(0);
	for(i=0; i<points.length; i++) {
		latLngs.push(new PolylineEncoder.latLng(points[i][0], points[i][1]));
	}
	return latLngs;
}
PolylineEncoder.pointsToGLatLngs = function(points) {
	var i, gLatLngs;
	gLatLngs = new Array(0);
	for(i=0; i<points.length; i++) {
		gLatLngs.push(new GLatLng(points[i][0], points[i][1]));
	}
	return gLatLngs;
}

