var myMap=new GInit();

function GInit() {
  this.map;
  this.overview_init='';
  this.path_start='';
  this.path_points=[];
  this.path_segments=[];
  this.map_click_option='mark';
  return this;
}

function GLoad() {
  if (GBrowserIsCompatible()) {
    //
    // create map:
    //
    myMap.map=new GMap2(document.getElementById('map'));

    //
    // setup map controls:
    //
    var GLMC=new GLargeMapControl();
    var GMTC=new GMapTypeControl();
    var GSC=new GScaleControl();
    //var GOMC=new GOverviewMapControl(new GSize(150,150));

    //
    // special setup for overview control:
    //
    //myMap.map.addControl(GOMC, new GControlPosition(G_ANCHOR_BOTTOM_RIGHT, new GSize(0,0)));
    //document.getElementById('map_overview').style.visibility='hidden';
    //document.getElementById('map_overview').style.display='none';

    //
    // enable default keyboard navigation:
    //
    var keys=new GKeyboardHandler(myMap.map);

    //
    // add listeners to toggle map controls based on mouseover:
    //
    GEvent.addListener(myMap.map, 'mouseover', function() {
      myMap.map.addControl(GLMC);
      myMap.map.addControl(GMTC);
      myMap.map.addControl(GSC);
      //if (myMap.overview_init == 0) overviewMapInit(GOMC);
      //document.getElementById("map_overview").style.visibility='visible';
      //document.getElementById("map_overview").style.display='';

    });

    GEvent.addListener(myMap.map, 'mouseout', function() {
      myMap.map.removeControl(GLMC);
      myMap.map.removeControl(GMTC);
      myMap.map.removeControl(GSC);
//      document.getElementById("map_overview").style.visibility='hidden';
//      document.getElementById("map_overview").style.display='none';
    });

    //
    // add listener to respond to mouse clicks:
    //
    GEvent.addListener(myMap.map, 'click', function(marker, point) {
      if (myMap.map_click_option == 'mark')
        //
        // add or remove marks on click:
        //
        if (marker) {
          //
          // remove the marker:
          //
          myMap.map.removeOverlay(myMap.path_segments[myMap.path_segments.length-1]);
          myMap.path_segments.pop();
          myMap.path_points.pop();
          if (myMap.path_points.length == 0) myMap.map.removeOverlay(marker);
        } 
        else {
          //
          // add the first marker:
          //
          if (myMap.path_points.length == 0) {
            //
            // simple marker:
            //
            myMap.path_start=new GMarker(point);
            myMap.map.addOverlay(myMap.path_start);
            //
            // draggable marker:
            //
            //myMap.path_start=new GMarker(point, {draggable:true});
            //myMap.map.addOverlay(myMap.path_start);
            //myMap.path_start.enableDragging();
          }
          //
          // add a subsequent marker:
          //
          myMap.path_points.push(new GLatLng(point.lat(), point.lng()));

          if (myMap.path_points.length > 1) {
            var lastpoints=[];
            lastpoints.push(myMap.path_points[myMap.path_points.length-2]);
            lastpoints.push(myMap.path_points[myMap.path_points.length-1]);
            var path_segment=new GPolyline(lastpoints,'#00ff00',2);
            myMap.path_segments.push(path_segment);
            myMap.map.addOverlay(path_segment);
          }
      }
      if (myMap.map_click_option == 'center') {
        //
        // center on click:
        //
        myMap.map.panTo(point);
      }
      if (myMap.map_click_option == 'zoom') {
        //
        // center and zoom on click:
        //
        myMap.map.setCenter(point);
        myMap.map.zoomIn();
      }
    });

    //
    // init the map:
    //
    mainMapInit('map1');
  }
}

function overviewMapInit(control) {
  //
  // configure the overview map:
  //
  var ovmap=control.getOverviewMap();
  if (ovmap) {
    ovmap.setMapType(G_NORMAL_MAP);
    //ovmap.addControl(new GSmallMapControl());
  }
  //
  // configure the overview container:
  //
  var ovmapcontainer=document.getElementById('map_overview');
  if (ovmapcontainer) {
    //
    // style the overview container:
    //
    ovmapcontainer.firstChild.style.border='1px solid gray';
    ovmapcontainer.firstChild.firstChild.style.left='4px';
    ovmapcontainer.firstChild.firstChild.style.top='4px';
    ovmapcontainer.firstChild.style.background='#FFFFFF';
    //
    // append overview container to main map and position it:
    //
    var mapdiv=document.getElementById('map');
    mapdiv.appendChild(ovmapcontainer);

    ovmapcontainer.style.position='relative';

    var mh=parseInt(mapdiv.style.height);
    var oh=parseInt(ovmapcontainer.style.height);
    ovmapcontainer.style.top=(mh-oh)+'px';

    var mw=parseInt(mapdiv.style.width);
    var ow=parseInt(ovmapcontainer.style.width);
    ovmapcontainer.style.left=(mw-ow)+'px';
  }
  myMap.overview_init=1;
}

function mainMapInit(map_folder) {
  //
  // clear the map:
  //
  myMap.map.clearOverlays();

  //
  // configure map:
  //
  GDownloadUrl('services/google_maps/'+map_folder+'/map-settings.xml', function(data, responseCode) {
    var xml=GXml.parse(data);
    var settings=xml.documentElement.getElementsByTagName('settings');
    var center_lat=parseFloat(settings[0].getAttribute('center_lat'));
    var center_lng=parseFloat(settings[0].getAttribute('center_lng'));
    var default_zoom=parseInt(settings[0].getAttribute('default_zoom'));
    myMap.map.setCenter(new GLatLng(center_lat, center_lng), default_zoom, G_HYBRID_MAP);
  });

  //
  // draw map objects:
  //
  GDownloadUrl('services/google_maps/map-objects-list.cfm?map='+map_folder, function(data, responseCode) {
    var result=data.replace(/^\s*|\s*$/g,'');
    if (result=='') return;
    result=result.split(',');
    for (var i=0; i < result.length; i++) {
      GDownloadUrl('services/google_maps/'+map_folder+'/objects/'+result[i], function(data, responseCode) {
        var xml=GXml.parse(data);
        var points=[];
        var markers=xml.documentElement.getElementsByTagName('marker');
        var settings=xml.documentElement.getElementsByTagName('settings');
        for (var j=0; j < markers.length; j++) {
          points.push(new GLatLng(markers[j].getAttribute('lat'), markers[j].getAttribute('lng')));
        }
        myMap.map.addOverlay(new GPolyline(points,'#'+settings[0].getAttribute('lineColor'),parseInt(settings[0].getAttribute('lineWidth')),parseFloat(settings[0].getAttribute('lineOpacity'))));
      });
    }
  });

  //
  // draw map icons:
  //
  GDownloadUrl('services/google_maps/map-icons-list.cfm?map='+map_folder, function(data, responseCode) {
    var result=data.replace(/^\s*|\s*$/g,'');
    if (result=='') return;
    result=result.split(',');
    for (var i=0; i < result.length; i++) {
      GDownloadUrl('services/google_maps/'+map_folder+'/icons/'+result[i], function(data, responseCode) {
        var xml=GXml.parse(data);
        var markers=xml.documentElement.getElementsByTagName('marker');
        var settings=xml.documentElement.getElementsByTagName('settings');
        var icon;
        for (var j=0; j < markers.length; j++) {
          icon=new GIcon();
          icon.image='services/google_maps/'+settings[0].getAttribute('icon_path');
          icon.iconSize=new GSize(11,12);
          icon.iconAnchor=new GPoint(6,6);
          myMap.map.addOverlay(new GMarker(new GLatLng(markers[j].getAttribute('lat'), markers[j].getAttribute('lng')), icon, 1));
          myMap.map.addOverlay(new ELabel(new GLatLng(markers[j].getAttribute('lat'), markers[j].getAttribute('lng')), markers[j].getAttribute('caption'), 'elabel', new GSize(parseInt(markers[j].getAttribute('offsetx')),parseInt(markers[j].getAttribute('offsety')))));
        }
      });
    }
  });

  //
  // draw map overlays:
  //
  GDownloadUrl('services/google_maps/map-overlays-list.cfm?map='+map_folder, function(data, responseCode) {
    var result=data.replace(/^\s*|\s*$/g,'');
    if (result=='') return;
    result=result.split(',');
    for (var i=0; i < result.length; i++) {
      GDownloadUrl('services/google_maps/'+map_folder+'/overlays/'+result[i], function(data, responseCode) {
        var xml=GXml.parse(data);
        var markers=xml.documentElement.getElementsByTagName('marker');
        for (var j=0; j < markers.length; j++) {
          var insert=new EInsert(new GLatLng(markers[j].getAttribute('lat'), markers[j].getAttribute('lng')), 'services/google_maps/'+map_folder+'/overlays/'+markers[j].getAttribute('overlay'), new GSize(markers[j].getAttribute('width'),markers[j].getAttribute('height')), markers[j].getAttribute('zoom'));
          myMap.map.addOverlay(insert);
        }
      });
    }
  });
}

function clearPath() {
  for (var i=0; i<myMap.path_segments.length; i++) {
    myMap.map.removeOverlay(myMap.path_segments[i]);
  }
  myMap.path_points.length=0
  myMap.path_segments.length=0
  myMap.map.removeOverlay(myMap.path_start);
}

function showPath() {
  if (myMap.path_points.length < 2) {
    alert('Not enough points for a path.<br><br>Click TWO or more points on the map to create a path.<br><br>');
    return;
  }
  //
  // draw path:  
  //
  myMap.map.addOverlay(new GPolyline(myMap.path_points,'#'+$F('lineColor'),parseInt($F('lineWidth')),parseFloat($F('lineOpacity'))));
  //
  // open xml in new window:  
  //
  var x='<path>';
  x += '<comment>';
  x += 'In this demo, this file is simply displayed onscreen. ';
  x += 'In production use, this file is written to the server, causing a new persistent map annotation of a path to appear on the specified map. ';
  x += 'The path is drawn by connecting the user-specified points with line segments, using the user-specified line width and line color and line opacity. ';
  x += '</comment>';
  for (var i=0; i<myMap.path_points.length; i++) {
    x += '<marker ';
    x += 'lat=\"' + myMap.path_points[i].lat() + '\" ';
    x += 'lng=\"' + myMap.path_points[i].lng() + '\" ';
    x += '/>';
  }
  x += '<settings ';
  x += 'lineColor=\"' + $F('lineColor') + '\" ';
  x += 'lineWidth=\"' + $F('lineWidth') + '\" ';
  x += 'lineOpacity=\"' + $F('lineOpacity') + '\" ';
  x += ' />';
  x += '</path>';
  window.open('services/google_maps/map-path.cfm?x='+x,'_blank','toolbar=no, location=no, directories=no, status=no, menubar=yes, scrollbars=yes, resizable=yes, width=600, height=400');
  clearPath();
}

function showRegion() {
  if (myMap.path_points.length < 3) {
    alert('Not enough points for a region.<br><br>Click THREE or more points on the map to create a region.<br><br>');
    return;
  }
  //
  // draw region:  
  //
  var points=[];
  for(var i=0; i<myMap.path_points.length; i++) {
    points.push(myMap.path_points[i]);
  }
  points.push(myMap.path_points[0]);
  myMap.map.addOverlay(new GPolyline(points,'#'+$F('lineColor'),parseInt($F('lineWidth')),parseFloat($F('lineOpacity'))));
  //
  // open xml in new window:
  //
  var x='<region>';
  x += '<comment>';
  x += 'In this demo, this file is simply displayed onscreen. ';
  x += 'In production use, this file is written to the server, causing a new persistent map annotation of a region (closed polygon) to appear on the specified map. ';
  x += 'The region is drawn by connecting the user-specified points with line segments, using the user-specified line width and line color and line opacity. ';
  x += '</comment>';
  for (var i=0; i<myMap.path_points.length; i++) {
    x += '<marker ';
    x += 'lat=\"' + myMap.path_points[i].lat() + '\" ';
    x += 'lng=\"' + myMap.path_points[i].lng() + '\" ';
    x += '/>';
  }
  x += '<marker ';
  x += 'lat=\"' + myMap.path_points[0].lat() + '\" ';
  x += 'lng=\"' + myMap.path_points[0].lng() + '\" ';
  x += '/>';
  x += '<settings ';
  x += 'lineColor=\"' + $F('lineColor') + '\" ';
  x += 'lineWidth=\"' + $F('lineWidth') + '\" ';
  x += 'lineOpacity=\"' + $F('lineOpacity') + '\" ';
  x += ' />';
  x += '</region>';
  window.open('services/google_maps/map-region.cfm?x='+x,'_blank','toolbar=no, location=no, directories=no, status=no, menubar=yes, scrollbars=yes, resizable=yes, width=600, height=400');
  clearPath();
}

function showArrow() {
  if (myMap.path_points.length < 4) {
    alert('Not enough points for an arrow.<br><br>Click FOUR or more points on the map to create a arrow.<br><br>');
    return;
  }
  //
  // draw arrow:  
  //
  var points=[];
  points.push(new GPoint(myMap.path_points[0].lng(), myMap.path_points[0].lat()));
  points.push(new GPoint(myMap.path_points[1].lng(), myMap.path_points[1].lat()));
  points.push(new GPoint(myMap.path_points[2].lng(), myMap.path_points[2].lat()));
  points.push(new GPoint(myMap.path_points[1].lng(), myMap.path_points[1].lat()));
  points.push(new GPoint(myMap.path_points[3].lng(), myMap.path_points[3].lat()));
  points.push(new GPoint(myMap.path_points[1].lng(), myMap.path_points[1].lat()));
  myMap.map.addOverlay(new GPolyline(points,'#'+$F('lineColor'),parseInt($F('lineWidth')),parseFloat($F('lineOpacity'))));
  //
  // open xml in new window:
  //
  var x='<arrow>';
  x += '<comment>';
  x += 'In this demo, this file is simply displayed onscreen. ';
  x += 'In production use, this file is written to the server, causing a new persistent map annotation of an arrow to appear on the specified map. ';
  x += 'The arrow is drawn by connecting the user-specified points with line segments, using the user-specified line width and line color and line opacity. ';
  x += '</comment>';
  x += '<marker lat=\"' + myMap.path_points[0].lat() + '\" lng=\"' + myMap.path_points[0].lng() + '\"/>';
  x += '<marker lat=\"' + myMap.path_points[1].lat() + '\" lng=\"' + myMap.path_points[1].lng() + '\"/>';
  x += '<marker lat=\"' + myMap.path_points[2].lat() + '\" lng=\"' + myMap.path_points[2].lng() + '\"/>';
  x += '<marker lat=\"' + myMap.path_points[1].lat() + '\" lng=\"' + myMap.path_points[1].lng() + '\"/>';
  x += '<marker lat=\"' + myMap.path_points[3].lat() + '\" lng=\"' + myMap.path_points[3].lng() + '\"/>';
  x += '<marker lat=\"' + myMap.path_points[1].lat() + '\" lng=\"' + myMap.path_points[1].lng() + '\"/>';
  x += '<settings ';
  x += 'lineColor=\"' + $F('lineColor') + '\" ';
  x += 'lineWidth=\"' + $F('lineWidth') + '\" ';
  x += 'lineOpacity=\"' + $F('lineOpacity') + '\" ';
  x += ' />';
  x += '</arrow>';
  window.open('services/google_maps/map-arrow.cfm?x='+x,'_blank','toolbar=no, location=no, directories=no, status=no, menubar=yes, scrollbars=yes, resizable=yes, width=600, height=400');
  clearPath();
}

function showCircle() {
  if (myMap.path_points.length < 2) {
    alert('Not enough points for a circle.<br><br>Click TWO or more points on the map to create a circle.<br><br>');
    return;
  }
  //
  // draw circle:  
  //
  var points=[];
  var circleSegments=20;
  var center=myMap.path_points[0];
  var circleDistortion=800/700; // to account for map region not being a true square
  var radiusDistortion=700/800; // to account for map region not being a true square
  //
  // radius calc based on code by Hexa Software Development Center:
  //
  var radlat1=((Math.PI * myMap.path_points[0].lat())/180);
  var radlat2=((Math.PI * myMap.path_points[1].lat())/180);
  var radlon1=((Math.PI * myMap.path_points[0].lng())/180);
  var radlon2=((Math.PI * myMap.path_points[1].lng())/180);
  var theta=myMap.path_points[0].lng()-myMap.path_points[1].lng();
  var radtheta=((Math.PI * theta)/180);
  var dist=((60 * 1.15151515) * (180 / Math.PI) * (Math.acos((Math.sin(radlat1) * Math.sin(radlat2)) + (Math.cos(radlat1) * Math.cos(radlat2) * Math.cos(radtheta)))));
  var raddist=(Math.PI * dist)/180;
  var radius=raddist*radiusDistortion;
  for(var i=0; i<=360; i+=(360/circleSegments)) {
    points.push(new GPoint(center.x + (radius * Math.cos(i * (Math.PI / 180))) * circleDistortion, center.y + (radius * Math.sin(i * (Math.PI / 180)))));
  }
  myMap.map.addOverlay(new GPolyline(points,'#'+$F('lineColor'),parseInt($F('lineWidth')),parseFloat($F('lineOpacity'))));
  //
  // open xml in new window:  
  //
  var x='<circle>';
  x += '<comment>';
  x += 'In this demo, this file is simply displayed onscreen. ';
  x += 'In production use, this file is written to the server, causing a new persistent map annotation of a circle to appear on the specified map. ';
  x += 'The circle is drawn by calculating a set of points around the first user-specified point and then conecting those points using the user-specified line width, line color and line opacity. ';
  x += '</comment>';
  for(var i=0; i<=360; i+=(360/circleSegments)) {
    x += '<marker ';
    x += 'lat=\"' + parseFloat(center.y + (radius * Math.sin(i * (Math.PI / 180)))) + '\" ';
    x += 'lng=\"' + parseFloat(center.x + (radius * Math.cos(i * (Math.PI / 180))) * circleDistortion) + '\" ';
    x += '/>';
  }
  x += '<settings ';
  x += 'lineColor=\"' + $F('lineColor') + '\" ';
  x += 'lineWidth=\"' + $F('lineWidth') + '\" ';
  x += 'lineOpacity=\"' + $F('lineOpacity') + '\" ';
  x += ' />';
  x += '</circle>';
  window.open('services/google_maps/map-circle.cfm?x='+x,'_blank','toolbar=no, location=no, directories=no, status=no, menubar=yes, scrollbars=yes, resizable=yes, width=600, height=400');
  clearPath();
}

function showSquare() {
  if (myMap.path_points.length < 2) {
    alert('Not enough points for a square.<br><br>Click TWO or more points on the map to create a square.<br><br>');
    return;
  }
  //
  // draw square:  
  //
  var points=[];
  points.push(new GPoint(myMap.path_points[0].lng(), myMap.path_points[0].lat()));
  points.push(new GPoint(myMap.path_points[0].lng(), myMap.path_points[1].lat()));
  points.push(new GPoint(myMap.path_points[1].lng(), myMap.path_points[1].lat()));
  points.push(new GPoint(myMap.path_points[1].lng(), myMap.path_points[0].lat()));
  points.push(new GPoint(myMap.path_points[0].lng(), myMap.path_points[0].lat()));
  myMap.map.addOverlay(new GPolyline(points,'#'+$F('lineColor'),parseInt($F('lineWidth')),parseFloat($F('lineOpacity'))));
  //
  // open xml in new window:  
  //
  var x='<square>';
  x += '<comment>';
  x += 'In this demo, this file is simply displayed onscreen. ';
  x += 'In production use, this file is written to the server, causing a new persistent map annotation of a square to appear on the specified map. ';
  x += 'The square is drawn by considering the first two user-specified points as a diagonal and then drawing a square around that diagonal, using the user-specified line width and line color and line opacity. ';
  x += '</comment>';
  x += '<marker lat=\"' + myMap.path_points[0].lat() + '\" lng=\"' + myMap.path_points[0].lng() + '\"/>';
  x += '<marker lat=\"' + myMap.path_points[0].lat() + '\" lng=\"' + myMap.path_points[1].lng() + '\"/>';
  x += '<marker lat=\"' + myMap.path_points[1].lat() + '\" lng=\"' + myMap.path_points[1].lng() + '\"/>';
  x += '<marker lat=\"' + myMap.path_points[1].lat() + '\" lng=\"' + myMap.path_points[0].lng() + '\"/>';
  x += '<marker lat=\"' + myMap.path_points[0].lat() + '\" lng=\"' + myMap.path_points[0].lng() + '\"/>';
  x += '<settings ';
  x += 'lineColor=\"' + $F('lineColor') + '\" ';
  x += 'lineWidth=\"' + $F('lineWidth') + '\" ';
  x += 'lineOpacity=\"' + $F('lineOpacity') + '\" ';
  x += ' />';
  x += '</square>';
  window.open('services/google_maps/map-square.cfm?x='+x,'_blank','toolbar=no, location=no, directories=no, status=no, menubar=yes, scrollbars=yes, resizable=yes, width=600, height=400');
  clearPath();
}

function showIcons() {
  if (myMap.path_points.length < 1) {
    alert('Not enough points to place icons.<br><br>Click ONE or more points on the map to place icons.<br><br>');
    return;
  }
  //
  // draw icons:  
  //
  var icon;
  for (var j=0; j < myMap.path_points.length; j++) {
    icon=new GIcon();
    icon.image='services/google_maps/map-icon01.png';
    icon.iconSize=new GSize(11,12);
    icon.iconAnchor=new GPoint(6,6);
    myMap.map.addOverlay(new GMarker(new GLatLng(myMap.path_points[j].lat(), myMap.path_points[j].lng()), icon, 1));
    myMap.map.addOverlay(new ELabel(new GLatLng(myMap.path_points[j].lat(), myMap.path_points[j].lng()), 'caption'+j, 'elabel', new GSize(0, 0)));
  }
  //
  // open xml in new window:  
  //
  var x='<icons>';
  x += '<comment>';
  x += 'In this demo, this file is simply displayed onscreen. ';
  x += 'In production use, this file is written to the server, causing a new persistent map annotation of a set of labeled icons to appear on the specified map. ';
  x += '</comment>';
  for (var i=0; i<myMap.path_points.length; i++) {
    x += '<marker ';
    x += 'lat=\"' + myMap.path_points[i].lat() + '\" ';
    x += 'lng=\"' + myMap.path_points[i].lng() + '\" ';
    x += 'caption=\"caption' + i + '\" ';
    x += 'offsetx=\"0\" ';
    x += 'offsety=\"0\" ';
    x += '/>';
  }
  x += '<settings ';
  x += 'icon_path=\"map-icon01.png\" ';
  x += ' />';
  x += '</icons>';
  window.open('services/google_maps/map-icons.cfm?x='+x,'_blank','toolbar=no, location=no, directories=no, status=no, menubar=yes, scrollbars=yes, resizable=yes, width=600, height=400');
  clearPath();
}

function showSettings() {
  //
  // open xml in new window:  
  //
  var center=myMap.map.getCenter();
  var x='<map>';
  x += '<comment>';
  x += 'In this demo, this file is simply displayed onscreen. ';
  x += 'In production use this file is written to the server, causing a new entry to appear on the map thumbnail toolbar. ';
  x += '</comment>';
  x += '<settings ';
  x += 'center_lat=\"' + center.lat() + '\" ';
  x += 'center_lng=\"' + center.lng() + '\" ';
  x += 'default_zoom=\"' + myMap.map.getZoom() + '\" ';
  x += ' />';
  x += '</map>';
  window.open('services/google_maps/map-settings.cfm?x='+x,'_blank','toolbar=no, location=no, directories=no, status=no, menubar=yes, scrollbars=yes, resizable=yes, width=600, height=400');
  clearPath();
}

function zoomToFit() {
  //
  // zoom to fit:
  //
  var bounds=new GLatLngBounds();
  for(var i=0; i < myMap.path_points.length; i++) {
    bounds.extend(myMap.path_points[i]);
  }
  var lngCenter=(bounds.getNorthEast().lng() + bounds.getSouthWest().lng()) / 2;
  var latCenter=(bounds.getNorthEast().lat() + bounds.getSouthWest().lat()) / 2;
  var center=new GLatLng(latCenter,lngCenter);
  myMap.map.setCenter(center, myMap.map.getBoundsZoomLevel(bounds));
}
