
var tinyicon = null;
var map = null;


function processXml() {
   //alert("In processXml()");
   var f = document.user_options;  // This is the form we'll we working with.
   var selectBox = f.xml_file
   var url = selectBox.options[selectBox.selectedIndex].value
   //document.forms[0].select.selectedIndex = 2;

   buildMap(url);

   map.centerAndZoom(centerPoint, getZoomLevel(x));
 
}


function buildMap(route_url) {

   if (initImap() == 0) {
      map.clearOverlays();

      loadXMLDoc(route_url);
   }

   function initImap() {
      if (GBrowserIsCompatible()) {
         if (tinyicon == null) {
            tinyicon = new GIcon();
            tinyicon.image = "http://labs.google.com/ridefinder/images/mm_20_green.png";
            tinyicon.shadow = "http://labs.google.com/ridefinder/images/mm_20_shadow.png";
            tinyicon.iconSize = new GSize(12, 20);
            tinyicon.shadowSize = new GSize(22, 20);
            tinyicon.iconAnchor = new GPoint(6, 20);
            tinyicon.infoWindowAnchor = new GPoint(5, 1);
         }

         if (map == null) {
            //alert("Creating a new Map instance.");
            map = new GMap(document.getElementById("map"));
            map.addControl(new GSmallMapControl());
            map.addControl(new GMapTypeControl());
            map.addControl(new GScaleControl());

//            map.centerAndZoom(new GPoint(-81.373973, 28.432274), 9);
            //var bccPoint = new GPoint(-80.67166, 28.16788);
            //var orlandoPoint = new GPoint(-81.373973, 28.432274);
            //map.centerAndZoom(bccPoint, 5);
            //map.centerAndZoom(orlandoPoint, 8);

            //var center = getCenterLatLng();
            //var html = "<span class=\"small\">Wickham Pavilion<br>(next to BCC Campus)</span>";
            //var marker = createMapMarker(new GPoint(-80.67166, 28.16788), html, "red");
            //map.addOverlay(marker);

            GEvent.addListener(map, 'click', function(overlay, point) {
               if (point) {
                  //alert("Clicked on point!!! " + point);
                  //map.addOverlay(new GMarker(point));
                  document.getElementById('coordinate').innerHTML=point;
                  //     document.getElementById('A1').innerHTML=xmlhttp.status
                  //     document.getElementById('A2').innerHTML=xmlhttp.statusText
                  //     document.getElementById('A3').innerHTML=xmlhttp.responseText
                  //alert("Clicked on point 1 " + point);

                  //document.getElementById('debug').innerHTML="Before createMarker 1 for " + point;

                  map.addOverlay(createMapMarker(point, "", "yellow"));
                  //alert("Clicked on point 2 " + point);
               }
            });
         }
         return 0;
      }
      else {
         alert("Sorry, your browser is not compatible with the Google Maps API.\n\n" +
               "Google Maps currently supports recent versions of Firefox/Mozilla, IE 5.5+,\n" +
               "Safari 1.2+, and sort of supports Opera. IE 5.0 is not supported.");
         return -1;
      }
   }

   // Creates a marker whose info window displays html text
   function createMapMarker(point, html, color) {
      //document.getElementById('debug').innerHTML="createMarker 1 for " + point;

      var icon = new GIcon(tinyicon);

      //icon.image = "http://www.google.com/mapfiles/marker.png";
      if (color == "red") {
         icon.image = "http://labs.google.com/ridefinder/images/mm_20_red.png";
      }
      else if (color == "green") {
         icon.image = "http://labs.google.com/ridefinder/images/mm_20_green.png";
      }
      else if (color == "yellow") {
         icon.image = "http://labs.google.com/ridefinder/images/mm_20_yellow.png";
      }
      else if (color == "orange") {
         icon.image = "http://labs.google.com/ridefinder/images/mm_20_orange.png";
      }
      else if (color == "purple") {
         icon.image = "http://labs.google.com/ridefinder/images/mm_20_purple.png";
      }
      else if (color == "blue") {
         icon.image = "http://labs.google.com/ridefinder/images/mm_20_blue.png";
      }
      else if (color == "white") {
         icon.image = "http://labs.google.com/ridefinder/images/mm_20_white.png";
      }
      else {
         icon.image = "http://labs.google.com/ridefinder/images/mm_20_red.png";
      }

      var marker = new GMarker(point, icon);

      // Show this marker's index in the info window when it is clicked
      GEvent.addListener(marker, 'click', function() {
         if (html == "") {
            map.removeOverlay(marker);
         }
         else {
            marker.openInfoWindowHtml(html);
         }
      });

      return marker;
   }


    // Download the data in data.xml and load it on the map. The format we
    // expect is:
    //    <rte>
    //      <name>EW-IndianHarbor-WOT</name>
    //      <rtept lat="28.151286" lon="-80.599844">
    //        <time>2005-06-22T17:55:56Z</time>
    //        <name>1302BananaRiver</name>
    //        <cmt>1302 Banana River Dr</cmt>
    //        <desc>1302 Banana River Dr</desc>
    //        <sym>Waypoint</sym>
    //      </rtept>
    //      <rtept lat="28.431330" lon="-80.788136">
    //        <name>Bre1005026</name>
    //        <cmt>Grissom Pky</cmt>
    //        <desc>Grissom Pky</desc>
    //        <sym>Waypoint</sym>
    //      </rtept>
    //      <rtept lat="28.553597" lon="-82.638057">
    //         <ele>3.352800</ele>
    //         <time>2005-09-13T15:48:55Z</time>
    //         <name>CTRL BAYPORT INN</name>
    //         <cmt>03-SEP-05 4:03:57PM</cmt>
    //         <desc>03-SEP-05 4:03:57PM</desc>
    //         <sym>Flag, Blue</sym>
    //      </rtept>
    //    </rte>
   var xmlhttp;

   function loadXMLDoc(url) {
      // code for Mozilla, etc.
      if (window.XMLHttpRequest) {
         xmlhttp=new XMLHttpRequest();
         xmlhttp.onreadystatechange=state_Change;
         xmlhttp.open("GET",url,true);
         xmlhttp.send(null);
      }
      // code for IE
      else if (window.ActiveXObject) {
         xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
         if (xmlhttp) {
            xmlhttp.onreadystatechange=state_Change;
            xmlhttp.open("GET",url,true);
            xmlhttp.send();
         }
      }
   }

   function state_Change() {
      // if xmlhttp shows "loaded"
      if (xmlhttp.readyState==4) {
         // if "OK"
         if (xmlhttp.status==200) {
            //alert("XML data OK");
            var xmlDoc = xmlhttp.responseXML;
            //alert("Starting on route points...");
            var rteElems = xmlDoc.documentElement.getElementsByTagName("rte");
            var nRtePts = plotRoute(rteElems);

            //alert("Starting on track elements...");
            var trkElems = xmlDoc.documentElement.getElementsByTagName("trk");
            plotTracks(trkElems, nRtePts);

//     document.getElementById('A1').innerHTML=xmlhttp.status
//     document.getElementById('A2').innerHTML=xmlhttp.statusText
//     document.getElementById('A3').innerHTML=xmlhttp.responseText
         }
         else {
            alert("Problem retrieving XML data:" + xmlhttp.statusText);
         }
      }
   }

   function plotRoute(rteElems) {
      //alert("Route points count = " + rteElems.length);

      if (rteElems.length > 0) {
         var rtName, name;
         var maxLon = -1000;
         var minLon =  1000;
         var maxLat = -1000;
         var minLat =  1000;
         var lon, lat;
//         var markers = new Array();
         var markerIdx = 0;
         var markers   = new Array(500); // TJ: debug
         var rtGPointArray = new Array();

         for (var i=0; i<rteElems.length; i++) {
            rtName = rteElems[i].getElementsByTagName("name")[0].childNodes[0].nodeValue + '<br>';

            var rtePtElems = rteElems[i].getElementsByTagName("rtept");

            if (rtePtElems.length > 0) {
               //alert("Processing route " + name + " with " + rtePtElems.length + " points.");

               //alert("rtePtElems count = " + rtePtElems.length);
               var gPoints = new Array(rtePtElems.length);
               var name, cmt, html, color;
               //var prevName  = null;
               //var prevPoint = null;

               for (var j=0; j<rtePtElems.length; j++) {
                  lon = parseFloat(rtePtElems[j].getAttribute("lon"));
                  lat = parseFloat(rtePtElems[j].getAttribute("lat"));

                  maxLon = Math.max(maxLon, lon);
                  minLon = Math.min(minLon, lon);
                  maxLat = Math.max(maxLat, lat);
                  minLat = Math.min(minLat, lat);

                  gPoints[j]  = new GPoint(lon, lat);

                  var point = new GPoint(lon, lat);
                  //var marker = createMapMarker(gPoints[j], "rtept", "orange");
                  name = rtePtElems[j].getElementsByTagName("name")[0].childNodes[0].nodeValue;

                  // Add a marker if the first char is not a \ (must be a .anr to .gpx conversion)
                  // and not number.
                  var re = /^[-]?\d*\.?\d*$/; // RegEx for a number
                  if (name.indexOf('\\') != 0 &&
                      ! name.match(re)) {

                     var cmtArray = rtePtElems[j].getElementsByTagName("cmt");
                     if (cmtArray.length > 0) {
                        cmt  = cmtArray[0].childNodes[0].nodeValue;
                        html = '<span class="small">' + rtName + name + '<br>' + cmt + '</span>';
                     }
                     else {
                        html = '<span class="small">' + rtName + name + '</span>';
                     }

                     rtName = "";

                     if (html.indexOf('CTRL') != -1) {
                        color = "red";
                     }
                     else if (j == 0) {
                        color = "green";
                     }
                     else {
                        color = "white";
                     }

                     // Add the marker
                     if (markers[point] == null) { // Point must be unique
                        var mkr = createMapMarker(point, html, color);
                        markers.length;
                        if (markerIdx < markers.length) {
                           markers[markerIdx] = mkr;
                           markerIdx++;
                        }
                        else {
                           markers[markers.length] = mkr;
                        }

                        //alert("Adding marker '" + name + "' typeof '" + (typeof name) + "'");
                        markers[point] = mkr;
                     }
                  }

                  // Debug code...
                  //if (prevPoint != null) {
                  //   var d = gcd(prevPoint.x, prevPoint.y, point.x, point.y);
                  //   if (d > 50) {
                  //      alert("Distance from '" + prevName + "' to '" + name + " is " + d + " miles.");
                  //   }
                  //}
                  //prevPoint = point;
                  //prevName  = name;
               }

               rtGPointArray[rtGPointArray.length] = gPoints;
            }
         }

         zoomAndCenter(maxLon, minLon, maxLat, minLat);

         for (var m=0; m<rtGPointArray.length; m++) {
            //alert("Plotting polyline " + (m+1) + " of " + rtGPointArray.length);
            plotPolyline(rtGPointArray[m], "#ff0000", 3, 0.4, 200);
         }

         //for (var k=0; k<markers.length; k++) {
         for (var k=markers.length - 1; k>=0; k--) {
            //if (k % 200 == 0) {
            //   alert("Overlayed " + k + " of " + markers.length + " markers.");
            //}
            if (markers[k] != null) {
               map.addOverlay(markers[k]);
            }
         }
         //alert("Finished overlaying "+ markers.length + " markers.");
      }
      return rteElems.length;
   }


   function plotTracks(trkElems, nRtePts) {
      if (trkElems.length > 0) {
         var name;
         var maxLon = -1000;
         var minLon =  1000;
         var maxLat = -1000;
         var minLat =  1000;
         var lon, lat;

         for (var i=0; i<trkElems.length; i++) {
            name = trkElems[i].getElementsByTagName("name")[0].childNodes[0].nodeValue;

            //alert("Processing track " + i + ", " + name);
            var trkPointElems = trkElems[i].getElementsByTagName("trkpt");

            // Add the trail head marker
            lon = parseFloat(trkPointElems[0].getAttribute("lon"));
            lat = parseFloat(trkPointElems[0].getAttribute("lat"));
            var html = '<span class="small">Trail Start<br>' + name + '</span>';
            var trlHeadMarker = createMapMarker(new GPoint(lon, lat), html, "purple");

            var gPoints = new Array(trkPointElems.length);
            var maxSize = 200;

            for (var j=0; j<trkPointElems.length; j++) {
               lon = parseFloat(trkPointElems[j].getAttribute("lon"));
               lat = parseFloat(trkPointElems[j].getAttribute("lat"));

               maxLon = Math.max(maxLon, lon);
               minLon = Math.min(minLon, lon);
               maxLat = Math.max(maxLat, lat);
               minLat = Math.min(minLat, lat);

               gPoints[j]  = new GPoint(lon, lat);
               //gPointsAA[j/maxSize][j % maxSize]  = new GPoint(lon, lat);
            }

            if (nRtePts == 0) {
               zoomAndCenter(maxLon, minLon, maxLat, minLat);
            }

            map.addOverlay(trlHeadMarker);

            //alert("  Making polyline...");
            plotPolyline(gPoints, "#ff00ff", 3, 0.4, 200);
         }
      }
   }

    // Plot a polyline in segments to avoid a bug in Mozilla
    function plotPolyline(gPoints, colorHex, weight, tranparency, chunkSize) {
       var size1    = gPoints.length / chunkSize; // 2682 / 100 = 26
       var lastSize = gPoints.length % chunkSize; // 2682 % 100 = 82

       // Array to repeatedly fill with points for each polyline segment.
       // Make it one bigger than the chunkSize to fill-in the gap between segments.
       var array = new Array(chunkSize + 1);
       var idx = 0;
       var polyline;

       for (var i=0; i < (size1 - 1); i++) {
          var jLast;
          for (var j=0; j<chunkSize; j++) {
             array[j] = gPoints[idx];

             idx = idx + 1;
             jLast = j;
          }

          if (lastSize > 0) {
             // Manually add duplicate of first point in the next section to
             // avoid a gap between polylines.
             array[jLast+1] = gPoints[idx];
          }

          polyline = new GPolyline(array, colorHex, weight, tranparency);
          //alert("  Overlaying polyline (" + i + ")...");
          map.addOverlay(polyline);
       }

       // Plot the last chuck
       array = new Array(lastSize);
       for (var j=0; j<lastSize; j++) {
          array[j] = gPoints[idx];

          idx = idx + 1;
       }
       polyline = new GPolyline(array, colorHex, weight, tranparency);
       //alert("  Overlaying polyline (" + gPoints.length + " points)...");
       map.addOverlay(polyline);
    }

    function avg(a, b) {
       return (a + b) / 2;
    }

    // Compute the great-circle distance between 2 geo-points (miles)
    function gcd(lon1, lat1, lon2, lat2) {
       //       dlon = lon2 - lon1
       //       dlat = lat2 - lat1
       //       a = (sin(dlat/2))^2 + cos(lat1) * cos(lat2) * (sin(dlon/2))^2
       //       c = 2 * arcsin(min(1,sqrt(a)))
       //       distance = (Earth Radius) * c
       var degToRadians = 3.141592658 / 180;

       var dlon = (lon2 - lon1) * degToRadians;
       var dlat = (lat2 - lat1) * degToRadians;
       var a = Math.pow((Math.sin(dlat/2)), 2) + Math.cos(lat1) * Math.cos(lat2) * Math.pow((Math.sin(dlon/2)), 2);
       //var c = 2 * Math.atan2( Math.sqrt(a), Math.sqrt(1-a) );
       var c = 2 * Math.asin(Math.min(1, Math.sqrt(a)));
       var d = 3964 * c;  // miles

       //alert("distance = " + d + " miles, between (" + lon1 + "," + lat1 + ") and (" +
       //      lon2 + "," + lat2 + ")");
       return d;
    }

    function getZoomLevel(distance) {
       var max = 3000;
       if (distance > max) {
          return 13;
       }
       else if (distance > (max/2)) {
          return 12;
       }
       else if (distance > (max/4)) {
          return 11;
       }
       else if (distance > (max/8)) {
          return 10;
       }
       else if (distance > (max/16)) { // 187
          return 9;
       }
       else if (distance > (max/32)) { // 94
          return 8;
       }
       else if (distance > (max/64)) { // 47
          return 7;
       }
       else if (distance > (max/128)) { // 24
          return 6;
       }
       else if (distance > (max/256)) { // 12
          return 5;
       }
       else if (distance > (max/512)) { // 6
          return 4;
       }
       else {
          return 3;
       }
    }

    var centerPoint;
    var x;

    function zoomAndCenter(maxLon, minLon, maxLat, minLat) {
       var spanLon = Math.abs(maxLon - minLon);
       var spanLat = Math.abs(maxLat - minLat);
       //alert("maxLon=" + maxLon + ",minLon=" + minLon +
       //      ",maxLat=" + maxLat + ",minLat=" + minLat +
       //      ",spanLon=" + spanLon + ",spanLat=" + spanLat);

       centerPoint = new GPoint(avg(maxLon, minLon),
                                    avg(maxLat, minLat));

       x = gcd(maxLon, minLat, minLon, maxLat);
       map.centerAndZoom(centerPoint, getZoomLevel(x));
    }
}
