﻿// JScript File
var points = [];
var marker = null;
var start_marker = null;
var highlighted_marker = null;
var end_marker = null;
var point_markers = [];
var totalDistance = 0;

function checkCoordinates(lat, lng, level)
{
  var pLat = parseFloat(lat);
  if (pLat.toString() != lat) {
    alert('Invalid latitude entered. Must be in range of -90 to 90');
    return false;
  }

  if (pLat < -90 || pLat > 90) {
    alert('Invalid latitude entered. Must be in range of -90 to 90');
    return false;
  }

  var pLong = parseFloat(lng);
  if (pLong.toString() != lng) {
    alert('Invalid longitude entered. Must be in range of -180 to 180');
    return false;
  }

  if (pLong < -180 || pLong > 180) {
    alert('Invalid longitude entered. Must be in range of -180 to 180');
    return false;
  }

  var pLevel = parseInt(level);
  if (pLevel.toString() != level) {
    alert('Invalid minimum level entered. Must be in range of 0 to 3');
    return false;
  }

  if (pLevel < 0 || pLevel > 3) {
    alert('Invalid minimum level entered. Must be in range of 0 to 3');
    return false;
  }
  
  return true;
}

// Add a point to the points list.
function addPoint(sLat, sLng, sLevel) {

  var sColor = "blue";
  
  var pLevel = parseInt(sLevel);
  
  if (!checkCoordinates(sLat, sLng, sLevel))
    return;

  createPoint(sLat, sLng, pLevel);
  createEncodings(false);
}

// Returns the index of the marker in the polyline.
function findMarkerIndex(point_marker) {
  var index = -1;

  for (var  i = 0; i < point_markers.length; ++i) {
    if (point_markers[i] == point_marker) {
      index = i;
      break;
    }
  }

  return index;
}

// Creates a point and adds it to both the polyline and the list.
function createPoint(lat, lng, pLevel, sColor) {

  if (!sColor)
    sColor = "red";

  if (point_markers.length == 0)
    sColor = "green";
  
  var newPoint = {
    Latitude: lat,
    Longitude: lng,
    Level: pLevel,
    Color: sColor
  };

  points.push(newPoint);

  if (marker) {
    document.map.removeOverlay(marker);
    marker = null;
  }

  var point_marker = createPointMarker(new GLatLng(lat, lng), sColor); //false
  document.map.addOverlay(point_marker);
  if (point_markers.length == 0)
      start_marker = point_marker;
  else
  {
      if (end_marker)
          changeColorFor(end_marker, "blue");
          
      end_marker = point_marker;
  }
      
  point_markers.push(point_marker);
}

// Creates a marker representing a point in the polyline.
function createPointMarker(point, clr) {
  //var clr = highlighted ? "yellow" : "blue";

  var point_marker = createMarker(point, clr);
  point_marker.enableDragging();

  GEvent.addListener(point_marker, "drag", function() {
    var index = findMarkerIndex(point_marker);

    if (index >= 0) {
      var nLat = point_marker.getPoint().lat();
      var nLng = point_marker.getPoint().lng();

      var pLevel = points[index].Level;
      var sColor = points[index].Color;

      var modifiedPoint = {
        Latitude: nLat,
        Longitude: nLng,
        Level: pLevel,
        Color: sColor
      };

      points[index] = modifiedPoint;
      createEncodings(false);
        
    }
    
  });

  GEvent.addListener(point_marker, "click", function() {
    if (oInterfaceText){
        if (window.confirm(oInterfaceText.getItemValue('TMTextDeleteOneText',1)))
            deleteMarker(point_marker);
        else
            if (window.confirm(oInterfaceText.getItemValue('TMTextDeleteAllText',1)))
                deleteAllPoints(true);
    }
  });

  return point_marker;
}

// Change color of the point specified by GMarker object in both the map and the point list.
function changeColorFor(oMarker, sColor)
{
    var nIndex = findMarkerIndex(oMarker);
    changeColorTo(nIndex, sColor);
}

// Change color of the point specified by index in both the map and the point list.
function changeColorTo(index, sColor) {
  var bStart = false;
  var bHighlited = false;
  var bEnd = false;
  var oPoint = null;

  if (point_markers[index] != null)
  {
      oPoint = point_markers[index].getPoint();
      
      if (point_markers[index] == start_marker)
            bStart = true;
      if (point_markers[index] == highlighted_marker)
            bHighlited = true;
      if (point_markers[index] == end_marker)
            bEnd = true;
            
      document.map.removeOverlay(point_markers[index]);

      point_markers[index] = createPointMarker(oPoint, sColor); //false
      document.map.addOverlay(point_markers[index]);

      if (bStart) start_marker = point_markers[index];
      if (bHighlited) highlighted_marker = point_markers[index];
      if (bEnd) end_marker = point_markers[index];
  }
}

// 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;
}

// Delete *all* the points from the polyline, with confirmation dialog before
// deletion.
function deleteAllPoints(bNoConfirm) {

  //var deleteConfirm;
  ///if (bNoConfirm)
  //   deleteConfirm = " ";
  //else
  //   deleteConfirm = confirm("Are you sure you want to remove all the points"
  //                            + " from this polyline?");

  //if (deleteConfirm) {
    points = [];
    deleteAllMarkers();
    createEncodings();
  //}
}

// Deletes all the markers for the points in the polyline
function deleteAllMarkers() {
  for(var i = 0; i < point_markers.length; ++i) {
    document.map.removeOverlay(point_markers[i]);
  }

  point_markers = [];
  start_marker = null;
  highlighted_marker = null;
  end_marker = null;
}

// Delete a point from the polyline.
function deleteMarker(oMarker) {
   var index = findMarkerIndex(oMarker);
   if (index > -1)
   {
        deletePoint(index);
   }
}

// Delete a point from the polyline.
function deletePoint(point_index) {
    var bStart = false;
    var bEnd = false;

    if (point_index >= 0 && point_index < points.length) {
      points.splice(point_index, 1);
      
      if (start_marker == point_markers[point_index]) {
        start_marker = null;
        bStart = true;
      }
      if (highlighted_marker == point_markers[point_index]) {
        highlighted_marker = null;
      }
      if (end_marker == point_markers[point_index]) {
        end_marker = null;
        bEnd = true;
      }

      document.map.removeOverlay(point_markers[point_index]);
      point_markers.splice(point_index, 1);
      
      if (bStart)
      {
        if (point_markers.length > 0)
        {
            changeColorTo(0, "green");
            start_marker = point_markers[0];
        }
      }
      if (bEnd)
      {
        if (point_markers.length > 1)
        {
            changeColorTo(point_markers.length-1, "red");
            end_marker = point_markers[point_markers.length-1];
        }
      }

      createEncodings();
    }

    if (points.length > 0) 
      if (point_index == 0) 
        point_index++;

     var oBtnTraces = document.getElementById('ButtonTraces1');
     if (oBtnTraces)
        oBtnTraces.applyTitle();

     var oBtnPushpin = document.getElementById('ButtonPushpin1');
     if (oBtnPushpin)
        oBtnPushpin.applyTitle();
}

// Try to encode an unsigned number. Used by the documentation.
function tryEncode() {
//  var txtValue = document.getElementById('txtNumber').value;
//  if (parseInt(txtValue).toString() == txtValue) {
//    document.getElementById('cdeValue').innerHTML
//      = encodeNumber(parseInt(txtValue));
//  }else{
//    document.getElementById('cdeValue').innerHTML = '(None)';
//  }
}

// Try to encode a signed number. Used by the documentation.
function trySignEncode() {
//  var txtValue = document.getElementById('txtSignNumber').value;
//  if (parseInt(txtValue).toString() == txtValue) {
//    document.getElementById('cdeSignValue').innerHTML
//      = encodeSignedNumber(parseInt(txtValue));
//  }else{
//    document.getElementById('cdeSignValue').innerHTML = '(None)';
//  }
}

// Create the encoded polyline and level strings. If moveMap is true
// move the map to the location of the first point in the polyline.
function createEncodings(moveMap) {
  var i = 0;

  var plat = 0;
  var plng = 0;

  var encoded_points = "";
  var encoded_levels = "";
  
  for(i = 0; i < points.length; ++i) {
    var point = points[i];
    var lat = point.Latitude;
    var lng = point.Longitude;
    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);
  }

  // move if moveMap is true.
  if (moveMap) {
    document.map.setCenter(
        new GLatLng(points[0].Latitude, points[0].Longitude),
        document.map.getZoom());
  }

  if (document.overlay) {
    document.map.removeOverlay(document.overlay);
  }

  if (document.overlay1) {
    document.map.removeOverlay(document.overlay1);
  }

        
  if (1 < points.length) {
    document.overlay = GPolyline.fromEncoded({color: "#FFFFFF",
                                              weight: 6,
                                              points: encoded_points,
                                              zoomFactor: 18,
                                              levels: encoded_levels,
                                              numLevels: 4
                                             });

    document.map.addOverlay(document.overlay);
    
    document.overlay1 = GPolyline.fromEncoded({color: "#FF0000",
                                              weight: 4,
                                              points: encoded_points,
                                              zoomFactor: 18,
                                              levels: encoded_levels,
                                              opacity: 0.8,
                                              numLevels: 4
                                             });

    document.map.addOverlay(document.overlay1);
   }
   
   // calculate distance and set encoded points value
   calculateDistanceAndSetEncoded(encoded_points);
}

function centerMap() {
}

// Decode an encoded polyline into a list of lat/lng tuples.
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;

    array.push([lat * 1e-5, lng * 1e-5]);
  }

  return array;
}

// Decode an encoded levels string into a list of levels.
function decodeLevels(encoded) {
  var levels = [];

  for (var pointIndex = 0; pointIndex < encoded.length; ++pointIndex) {
    var pointLevel = encoded.charCodeAt(pointIndex) - 63;
    levels.push(pointLevel);
  }

  return levels;
}

// Decode the supplied encoded polyline and levels.
function decode(encoded_points) {

  if (encoded_points.length==0) {
    return;
  }

  var enc_points = decodeLine(encoded_points);

  if (enc_points.length==0) {
    return;
  }

  deleteAllMarkers();
  points = [];

  for (var i = 0; i < enc_points.length; ++i) {
    var nLevel = 1;
    if ((i==0) || (i==enc_points.length-1))
        nLevel = 3;
    createPoint(enc_points[i][0], enc_points[i][1], nLevel);
  }

  createEncodings(false);
}

function displayPoints(bUpdate)
{
    if (marker) {
      document.map.removeOverlay(marker);
      marker = null;
    }

    //deleteAllMarkers();
    if (bUpdate)
        deleteAllPoints(true);
}

function createMarker(point, color) {
  
  //regular polyline window
  var f = new GIcon();
  f.image = "http://labs.google.com/ridefinder/images/mm_20_" + color + ".png";
  f.shadow = "http://labs.google.com/ridefinder/images/mm_20_shadow.png";
  f.iconSize = new GSize(12,20);
  f.shadowSize = new GSize(22,20);
  f.iconAnchor = new GPoint(6,20);
  f.infoWindowAnchor = new GPoint(6,1);
  f.infoShadowAnchor = new GPoint(13,13);

  newMarker = new GMarker(point,
    {icon: f,
     draggable: true});
     
  newMarker.bouncy = false;

  return newMarker;
}

function hideMarkers()
{
  for(var i = 0; i < point_markers.length; ++i) 
    point_markers[i].hide();
}

function showMarkers()
{
  for(var i = 0; i < point_markers.length; ++i)
    point_markers[i].show();
}

function calculateDistanceAndSetEncoded(sEncoded)
{
  totalDistance = 0;
  if (point_markers.length > 1)
      for(var i = 0; i < point_markers.length-1; ++i)
        totalDistance += point_markers[i].getPoint().distanceFrom(point_markers[i+1].getPoint());
        
  var oDistanceText = document.getElementById('DistanceText1');
  if (oDistanceText)
    oDistanceText.setDistance(totalDistance);

  var oButtonTraces = document.getElementById('ButtonTraces1');
  if (oButtonTraces)
    oButtonTraces.encoded=sEncoded;
}

function onClickPolylineDirections(point)
{
   if (point){
     var oBtnTraces = document.getElementById('ButtonTraces1');
     if (oBtnTraces){
        if (oBtnTraces.mode == 0)
            addPoint(point.lat().toString(), point.lng().toString(), '3');

        oBtnTraces.applyTitle();
     }

     var oBtnPushpin = document.getElementById('ButtonPushpin1');
     if (oBtnPushpin)
        oBtnPushpin.applyTitle();
   }
}


// Move the map to the selected point in the point list.
function jumpToPoint() {
  var pointList = document.getElementById('pointList');
  if (pointList.selectedIndex >= 0) {
    var point = points[pointList.selectedIndex];
    document.map.setCenter(new GLatLng(point.Latitude, point.Longitude),
                           document.map.getZoom());
  }
}



function createMainMarker(oMap, oPoint, sTitle)
{
//  var f = new GIcon();
//  f.image = "http://maps.google.com/mapfiles/arrow.png";
//  f.shadow = "http://www.google.com/intl/en_ALL/mapfiles/arrowshadow.png";
//  f.mozPrintImage = "http://maps.google.com/mapfiles/arrowff.gif";
//  f.printShadow = "http://maps.google.com/mapfiles/transparent.png";
//  f.iconSize = new GSize(39,34);
//  f.shadowSize = new GSize(22,20);
//  f.iconAnchor = new GPoint(6,20);
//  f.infoWindowAnchor = new GPoint(6,1);
//  f.infoShadowAnchor = new GPoint(13,13);

//    var oMarker = new GMarker(oPoint, {icon: f, draggable:true, title:sTitle});
   var oMarker = new GMarker(oPoint, {draggable:true, title:sTitle});
    oMap.addOverlay(oMarker); 

    GEvent.addListener(oMarker, "click", function() {
        onClickMainMarker(this);
    });
    
    GEvent.addListener(oMarker, "infowindowclose", function() {
        var oButton = document.getElementById("ButtonPushpin1");
        if (oButton.sText != this.title)
            oButton.recreateMarker();
    });
    
    GEvent.addListener(oMarker, "dragend", function() {
        var oButton = document.getElementById("ButtonPushpin1");
        if (oButton.oLabel)
            oButton.moveLabel(this.getPoint());
    });
    
    return oMarker;
}

function onClickMainMarker(oMarker)
{
      var oBtnPushpin = document.getElementById('ButtonPushpin1');
      if (oBtnPushpin){
          var sText = oBtnPushpin.sText;
          var sTabTxt = '';
          var sTabTxtLabel = '';
          var sTabCtrl = '';
          var sTabCtrlLabel = '';
          var sTabCtrlButton = '';
          if (oInterfaceText){
            sTabTxt = oInterfaceText.getItemValue('MMIWndTabTextTabName',1);
            sTabTxtLabel = oInterfaceText.getItemValue('MMIWndTabTextLabelName',1);
            sTabCtrl = oInterfaceText.getItemValue('MMIWndTabControlTabName',1);
            sTabCtrlLabel = oInterfaceText.getItemValue('MMIWndTabControlTabLabelName',1);
            sTabCtrlButton = oInterfaceText.getItemValue('MMIWndTabControlTabButtonName',1);
          }
          oMarker.openInfoWindowTabsHtml(
                [new GInfoWindowTab(sTabTxt,sTabTxtLabel + "<br><input type='text' id='txtMainMarkerTextInput' tabIndex=1 name='txtText' MAXLENGTH=30 value='" + sText 
                        + "' onkeypress='if((event.keyCode==13)||(event.keyCode==28)){var oBP=document.getElementById(\"ButtonPushpin1\");oBP.setText(this.value);oBP.closeInfoWindow()} else if(event.keyCode==27){document.getElementById(\"ButtonPushpin1\").closeInfoWindow()}'/>" 
                        + "<input type='button' name='btnOK' value='OK' onclick='var oText=document.getElementById(\"txtMainMarkerTextInput\");if (oText){var oBP=document.getElementById(\"ButtonPushpin1\");oBP.setText(oText.value);oBP.closeInfoWindow()}' />"), 
                 new GInfoWindowTab(sTabCtrl,sTabCtrlLabel + " <br><input type='button' name='btnDelete' value='" + sTabCtrlButton + "' onclick='document.getElementById(\"ButtonPushpin1\").deleteMainMarker();' />")
                 ]);
         var oText=document.getElementById('txtMainMarkerTextInput');
         if (oText)
         {
            window.setTimeout("document.getElementById('txtMainMarkerTextInput').focus();", 100);
         }
     }
}

