/* 
JavaScript funktioner til at styre Google Map relaterede funktioner

Authors: Lars Strange - irun.dk

 Change log
 V1.0 - 24. marts 2008
- Initial version
V1.01 - Fix for polyline click
 V1.1 - 31. aug. 2008
 - Sticky ruter / autorute
*/

// Test javascriptet bliver importeret korrekt
// alert('map.js loaded!');

//**********************************************************************
//***                    Initialisering af kort
//**********************************************************************

    var map = new GMap2(document.getElementById("map"),{draggableCursor:"crosshair"});
    var geocoder = new GClientGeocoder();
	map.addControl(new GLargeMapControl()); //GSmallMapControl GLargeMapControl
    map.addControl(new GMapTypeControl());
    map.setCenter(new GLatLng(38.272689, -23.203125), 2, G_NORMAL_MAP); // G_HYBRID_TYPE G_SATELLITE_MAP

    var points = [];
    var markers = [];
    var polyline;
	
	var directions = new GDirections();

    var showMilestones = true;
    var stickyLines = false;
    var c = (180 / Math.PI); // decimal to radian constant
    var totalDistance = 0.000;

    // Marker ikoner
	var icon = new GIcon();
	icon.image = "map_util/blank_km.png";
	icon.shadow = "map_util/km_shadow.png";
	icon.iconSize = new GSize(16, 34);
	icon.shadowSize = new GSize(22, 34);
	icon.iconAnchor = new GPoint(8, 34);
	icon.infoWindowAnchor = new GPoint(5, 1);

	var icon5 = new GIcon();
	icon5.image = "map_util/5.png";
	icon5.shadow = "map_util/km_shadow.png";
	icon5.iconSize = new GSize(16, 34);
	icon5.shadowSize = new GSize(22, 34);
	icon5.iconAnchor = new GPoint(8, 34);
	icon5.infoWindowAnchor = new GPoint(5, 1);
	
    // Start point anvender motion-online logo
    var startIcon = new GIcon();
    startIcon.image = "map_util/marker_start.png";
	startIcon.shadow = "map_util/km_shadow.png";
    startIcon.iconSize = new GSize(16, 34);
    startIcon.shadowSize = new GSize(22, 34);
    startIcon.iconAnchor = new GPoint(8, 34);
    startIcon.infoWindowAnchor = new GPoint(11, 2);
    startIcon.infoShadowAnchor = new GPoint(5, 1);
	
    // End point anvender motion-online logo
    var endIcon = new GIcon();
    endIcon.image = "map_util/logomarker.png";
	endIcon.shadow = "map_util/logomarker_shadow.png";
    endIcon.iconSize = new GSize(22, 32);
    endIcon.shadowSize = new GSize(39, 32);
    endIcon.iconAnchor = new GPoint(11, 32);
    endIcon.infoWindowAnchor = new GPoint(11, 2);
    endIcon.infoShadowAnchor = new GPoint(18, 25);

	map.enableScrollWheelZoom();

    GEvent.addListener(map, 'click', function(overlay, point) {
		if (overlay)
			return;
			   
        // hvis snap til street enabled
        if (stickyLines)
        {
            if (points.length == 0)
            {
                directions.loadFromWaypoints([point.toUrlValue(6), point.toUrlValue(6)], {getPolyline : true});        
            } else {
                directions.loadFromWaypoints([points[points.length-1].toUrlValue(6), point.toUrlValue(6)], {getPolyline : true});
            }
        }
        else
        {
            points.push(point);
            redrawRoute();
         }
    });

    // Tilføjer punkter fra autorute
    GEvent.addListener(directions, "load", function() {
      
      for (var i = 0; i < directions.getPolyline().getVertexCount(); i++)
      {
        var p = directions.getPolyline().getVertex(i);
        points.push(p);
      }
      redrawRoute();
    });


    parseURL();
//**********************************************************************
//***               Funktioner til at håndtere kortet
//**********************************************************************

    function redrawRoute() {
	  removeRoute();
	  
	  if (points.length != 0){
		  polyline = new GPolyline(points, "#C602C8", 5); // farve og tykkelse rettes her
		  map.addOverlay(polyline);
		  
		  // V1.01 - Fix for polyline click
          GEvent.addListener(polyline, 'click', function(point) {
              points.push(point);
              redrawRoute();
          });
		  
	  }

      var distance = 0;
      var last_point;
      for (var i = 0; i < points.length; i++) {
        if (i == 0) {
          createMarker2(points[i], i, true);
        } else {
		  var last_dist = calcRoutePiece(last_point,points[i]);
		  if (distance + last_dist > Math.ceil(distance)) {
			createMilestones(distance, last_dist, last_point, points[i]);
		  }
		  distance += last_dist;
		  
		  if (i == points.length-1) 
		    createMarker2(points[i], i, false);
        }
        last_point = points[i];
      }
      totalDistance = 0;
      
      if (polyline != null){
            totalDistance = polyline.getLength()/1000;
      }

      OpdaterKalorier(document.getElementById("vgt").value, totalDistance);
      OpdaterSkridt(document.getElementById("skridtLng").value, totalDistance);
      OpdaterHastighed(document.getElementById("speedMin").value, document.getElementById("speedSek").value, totalDistance);
	  OpdaterKondi(document.getElementById("speedMin2").value, document.getElementById("speedSek2").value, totalDistance);

      document.getElementById("distance").innerHTML = totalDistance.toFixed(3) + ' km';
      
    //  createEncodings()
    }

    function removeRoute() {
      if (polyline) {
        map.removeOverlay(polyline);
        polyline = null;
      }
      for (var i = 0; i < markers.length; i++) {
        map.removeOverlay(markers[i]);
      }
      markers = [];
    }

    function startOver() {
		points = [];
		document.getElementById("distance").innerHTML = "0.000";
		redrawRoute();
    }
    
     function removeLastPoint() {
		if (points.length == 0)
			return;
		points.pop();
		redrawRoute();
    }
    
	function toggleMilestones(chkBox) {
		showMilestones = chkBox.checked;
		redrawRoute();
	}
	
	function toggleStickyLines(chkBox)
	{
		stickyLines = chkBox.checked;
	}
    
    function createMilestone(point, distance) {
      var marker = null;
  	  var kmIcon = new GIcon();
	    kmIcon.shadow = "map_util/km_shadow.png";
	    kmIcon.iconSize = new GSize(16, 34);
	    kmIcon.shadowSize = new GSize(22, 34);
	    kmIcon.iconAnchor = new GPoint(8, 34);
	    kmIcon.infoWindowAnchor = new GPoint(5, 1);
      if (distance < 50) {
	    kmIcon.image = "map_util/" + distance + ".png";
   	    marker = new GMarker(point, kmIcon);
	  } else if ((distance > 49) && (distance < 100)){
	    if (distance % 10 == 0) {
	      kmIcon.image = "map_util/" + distance + ".png";
	      marker = new GMarker(point, kmIcon);
	    }
	  } else if ((distance > 99) && (distance < 549)){
	    if (distance % 50 == 0) {
	      kmIcon.image = "map_util/" + distance + ".png";
	      marker = new GMarker(point, kmIcon);
        }
      }
	  if (marker) {
		GEvent.addListener(marker, "click", function() {
			marker.openInfoWindowHtml(getDistanceInfo(distance));
		});
		map.addOverlay(marker);
		markers.push(marker);
      }
    }

    function createMilestone5(point) {
      var marker = new GMarker(point, icon5);
      map.addOverlay(marker);
      markers.push(marker);
    }

    function calcRoutePiece(startPoint, endPoint) {
        var lat1 = startPoint.y / c;
        var lat2 = endPoint.y / c;
        var lon1 = startPoint.x / c;
        var lon2 = endPoint.x / c;
		return 6378.7*Math.acos(Math.sin(lat1)*Math.sin(lat2)+Math.cos(lat1)*Math.cos(lat2)*Math.cos(lon2-lon1));
    }

    function createMarker2(point, pointIndex, isStart) {
      var marker;
      if (isStart){
        marker = new GMarker(point, {draggable:true, icon:startIcon});
      } else {
        marker = new GMarker(point, {draggable:true, icon:endIcon});
      }
      map.addOverlay(marker);
      marker.enableDragging();
      markers.push(marker);

	  GEvent.addListener(marker, "dragend", function(point){
	    points[pointIndex] = marker.getPoint();
	    redrawRoute();
	    });
    }

    function createMilestones(distance, last_distance, last_point, point) {
      if (!showMilestones)
		return;
      var dist = Math.ceil(distance);
      while (dist < distance + last_distance) {
        if (dist > 0) {
		  var fac = (dist - distance) / last_distance;
		  var dx = point.x - last_point.x;
		  var dy = point.y - last_point.y;
		  createMilestone(new GPoint(last_point.x+dx*fac,last_point.y+dy*fac),dist);
		}
		dist++;
      }
    }

    function getDistanceInfo(dist){
		var s = "<b>Distance:</b> " + dist + " km.<br />";

		return s;
	}
	
	function jumpToAddress(address) {
      if (geocoder) {
        geocoder.getLatLng(
          address,
          function(point) {
            if (!point) {
              alert("Location [" + address + "] could not be found.");
            } else {
              map.setCenter(point, 15);
//              var marker = new GMarker(point);
//              map.addOverlay(marker);
//              marker.openInfoWindowHtml(address);
            }
          }
        );
      }
    }
    
function getURL() {
    var e = createEncodings();
    var center = map.getCenter();
    var x = Math.round(100000 * center.x) / 100000;
    var y = Math.round(100000 * center.y) / 100000;
    var z = map.getZoom();
    var p = points.length;
    var s = 'x=' + x + '&y=' + y + '&z=' + z + '&points=' + p + '&route=' + e;
    location.href = "?" + s;
}
    

// Create the encoded polyline and level strings.
// Modified version of The Google Way ( http://code.google.com/apis/maps/documentation/polylineutility.html )
function createEncodings() {
  var i = 0;

  var plat = 0;
  var plng = 0;

  var encoded_points = "";
  var encoded_levels = "";

//  GLog.write("createEncodings");

  for(i = 0; i < points.length; ++i) {
    var point = points[i];
    var lat = point.y;
    var lng = point.x;
//    GLog.write("point.y= " + lat + " - point.x=" + lng);
//    var level = point.Level;

    var late5 = Math.floor(lat * 1e5);
    var lnge5 = Math.floor(lng * 1e5);

    dlat = late5 - plat;
    dlng = lnge5 - plng;

    plat = late5;
    plng = lnge5;

    encoded_points += encodeSignedNumber(dlat) + encodeSignedNumber(dlng);
//    encoded_levels += encodeNumber(level);
  }

//  document.getElementById('encodedLevels').value = encoded_levels;
//  document.getElementById('encodedPolyline').value = encoded_points;

//    GLog.write(encoded_points);
    
    return encoded_points;
}

// Encode a signed number in the encode format.
function encodeSignedNumber(num) {
  var sgn_num = num << 1;

  if (num < 0) {
    sgn_num = ~(sgn_num);
  }

  return(encodeNumber(sgn_num));
}

// Encode an unsigned number in the encode format.
function encodeNumber(num) {
  var encodeString = "";

  while (num >= 0x20) {
    encodeString += (String.fromCharCode((0x20 | (num & 0x1f)) + 63));
    num >>= 5;
  }

  encodeString += (String.fromCharCode(num + 63));
  return encodeString;
}



function parseURL(){
	var qs = new Querystring();
	var x = qs.get("x", "")
	var y = qs.get("y", "");
	var z = parseInt(qs.get("z", ""));
	var s = qs.get("route", "");
	var p = qs.get("points", "");
	if (s != "") {  	
		map.setCenter(new GLatLng(y,x), z);
	
	    var encodedLevels = "";
	    
	    for (var i = 0; i < p; i++){
	        encodedLevels = encodedLevels + "B";
	    }
//         GLog.write(encodedLevels);
        
        var encodedPolyline = new GPolyline.fromEncoded({
		    color: "#C602C8",
		    weight: 6,
		    points: s,
		    levels: encodedLevels,
		    zoomFactor: z,
		    numLevels: 4
	    });
	
        var vcount = encodedPolyline.getVertexCount();
        points = []
       
        for (var i =0; i < vcount; i++) { 
             points.push(encodedPolyline.getVertex(i)); 
        }
	
//		map.setZoom(z);
//		GLog.write(z);
//		map.setCenter(new GLatLng(y,x));
//		GLog.write(map.getZoom());
		redrawRoute();
	}
}


/* Client-side access to querystring name=value pairs
	Version 1.2.3
	22 Jun 2005
	Adam Vandenberg
*/
function Querystring(qs) { // optionally pass a querystring to parse
	this.params = new Object();
	this.get=Querystring_get;
	
	if (qs == null)
		qs=location.search.substring(1,location.search.length);

	if (qs.length == 0) return;

// Turn <plus> back to <space>
// See: http://www.w3.org/TR/REC-html40/interact/forms.html#h-17.13.4.1
	qs = qs.replace(/\+/g, ' ')
	var args = qs.split('&') // parse out name/value pairs separated via &
	
// split out each name=value pair
	for (var i=0;i<args.length;i++) {
		var value;
		var pair = args[i].split('=');
		var name = unescape(pair[0]);

		if (pair.length == 2)
			value = unescape(pair[1]);
		else
			value = name;
		
		this.params[name] = value;
	}
}

function Querystring_get(key, default_) {
	// This silly looking line changes UNDEFINED to NULL
	if (default_ == null) default_ = null;
	
	var value=this.params[key];
	if (value==null) value=default_;
	
	return value;
}

//**********************************************************************
//***                    Beregnere
//**********************************************************************


// Funktion til at opdatere visning af kalorieforbrug
function OpdaterKalorier(v, km){

    // foretag beregning
    var kalorier = BeregnKalorier(v, km).toFixed(0);
    
    // kontroller om beregningen kunne fuldføres
    if (kalorier == "NaN"){
        kalorier = "--";
    } else {
        kalorier = kalorier + " kcal";
    }
    
    // opdater span element
	document.getElementById("kalorier").innerHTML = kalorier;
}

// Funktion til at beregne kalorieforbrug
// Tager kun højde for dansk komma i input
function BeregnKalorier(v, km){
    v = v.toString().replace(",", ".");
	return v*km*1.055;
}

// Funktion til at opdatere visning af skridtlængde
function OpdaterSkridt(l, km){

    // foretag beregning
    var skridt = BeregnSkridt(l, km).toFixed(0);
    
    // kontroller om beregningen kunne fuldføres
    if (skridt == "NaN"){
        skridt = "--";
    } else {
        skridt = skridt + " steps";
    }
    
    // opdater span element
	document.getElementById("skridt").innerHTML = skridt;
}
	
// Funktion til at beregne antal skridt
function BeregnSkridt(l, km){

    // Tag højde for dansk komma i input
    l = l.toString().replace(",", ".");

	return (km*1000)/l;
}

// Funktion til at opdatere visning af hastigheder
function OpdaterHastighed(m, s, km){  

    // foretag beregning
    var kmTid = BeregnKmTid(m, s, km);
    
    // kontroller om beregningen kunne fuldføres
    if (kmTid == "NaN:NaN"){
        kmTid = "--";
    } else {
        kmTid = kmTid + " min:sec / km";
    }
    
    var speed = BeregnKmPerTime(m, s, km);
    if (speed == "NaN"){
        speed = "--";
    } else {
        speed = speed + " km/h";
    }
  
    
    // opdater span element
    document.getElementById("speed").innerHTML = speed;
	document.getElementById("kmTid").innerHTML = kmTid;
}

function BeregnKmPerTime(m, s, km){
    return (parseFloat(km) / ( (parseInt(s) + parseInt(m)*60) / (60*60) )).toFixed(2); // (m * 60 + s) / (60*60)
}

function BeregnKmTid(m, s, km){
    var totalSek = parseInt(m)*60 + parseInt(s);
    var totalSekPrKm = totalSek / parseFloat(km);
    var minPrKm = parseInt(totalSekPrKm / 60);
    var rest = totalSekPrKm - (minPrKm * 60);
    var sek = rest.toFixed(0);
    
    if (sek < 10) {    
        return minPrKm.toFixed(0) + ":0" + rest.toFixed(0) ;
    } else {
        return minPrKm.toFixed(0) + ":" + rest.toFixed(0) ;
    }
    
}

// Funktion til at opdatere visning af kondital
function OpdaterKondi(m2, s2, km){  

    // foretag beregning
    var kondital = Beregnkondital(m2, s2, km);
    
    // kontroller om beregningen kunne fuldføres
    if (kondital == "NaN"){
        kondital = "--";
    } else {
        kondital = kondital + " ml/kg/min";
    }
    
    
    // opdater span element
    document.getElementById("kondital").innerHTML = kondital;
}

function Beregnkondital(m2, s2, km){
	var KmPerTime2 = (parseFloat(km) / ( (parseInt(s2) + parseInt(m2)*60) / (60*60) )).toFixed(2); 
	return (3.5*(4.326+(0.862*KmPerTime2)-(-1.3264*Math.log(km) + 2.6934))).toFixed(1);
}
