// Copyright 2009 Google Inc.  All Rights Reserved.

/**
 * @fileoverview This file presents an example of a page that makes use of the
 *               Google Earth Plugin from a Google Earth Enterprise Server. It
 *               handles the following: examples of how to use the Google Earth
 *               Plugin API a simple layer panel for the layers provided by the
 *               GEE Server search tabs from the GEE Server Search Framework
 *               search results from the GEE Server.
 *
 * This file contains most of the work to customize the look and feel and
 * behaviors in the page as well as the calls to the plugin. Depends on :
 *   fusion_utils.js : some basic utilities for accessing DOM elements, and a
 *                     few low level utilities used by this example.
 *   search_tabs.js : sample classes for showing/managing search tabs and
 *                    results.
 *   earth_plugin_loader.js : do not modify...this code does the work to
 *                            load the plugin
 *
 * ASSUMES:
 *   GEE_SERVER_HOSTNAME is set
 * @author omitted
 */

/**
 * Load the specified javascript.
 * @param {string}
 *          path the path relative to the current web page of the javascript.
 */
//        var FUSION_MAP_SERVER = "http://portableearth";
//        var mapName = "default_map";
//        var earthName = "default_ge";
//http://scylla.exceptionalsoftware.com/EarthSpectorEarth1/
        var FUSION_MAP_SERVER = "http://scylla.exceptionalsoftware.com";
        var mapName = "default_map";
        var earthName = "SABLE_Demo";
        
        var _mFusionMapServer = FUSION_MAP_SERVER + "/" + mapName;
        var GEE_SERVER_URL = FUSION_MAP_SERVER + "/" + earthName + "/";
var bordercheckBoxId = "";
var borderlayerId = "";
var borderlayerName = "";

function geeLoadScript(path) {
  document.write('<script src="' + path +
                 '" type="text/javascript"><\/script>');
}

// Load the Earth database info into the JS global variable 'geeServerDefs'.
// This will have the fields:
// serverUrl : the url of the server
// isAuthenticated : true if the server is authenticated
// searchTabs : a JSON array of search tab definitions.
// layers : a JSON array of supplemental layer info
// If desired, you can point this to another GEE Server or use a different
// variable for multiple servers.
if (GEE_SERVER_URL == undefined) {
  var GEE_SERVER_URL = '';
}
geeLoadScript(GEE_SERVER_URL + 'query?request=Json&var=geeServerDefs');

var ge = null; // The Google Earth plugin object.
               // Initialized by the init() method on load.
// The div ids for the left panel, map and header.
// These must match the html and css declarations.
//    header: 'header',
//    leftPanelParent: 'left_panel_cell',
//    leftPanel: 'left_panel',
//var geeDivIds = {
//    map: 'map_canvas',
//    searchTabs: 'search_box',
//    searchTitle: 'search_results_title',
//    searchResults: 'search_panel',
//    layersTitle: 'layers_title',
//    layers: 'layers_panel'
//};
var geeDivIds = {
    header: 'header',
    map: 'map_canvas',
    leftPanelParent: 'left_panel_cell',
    leftPanel: 'left_panel',
    searchTabs: 'search_box',
    searchTitle: 'search_results_title',
    searchResults: 'search_results_container',
    layersTitle: 'layers_title',
    layers: 'layers_panel',
    collapsePanel: 'collapsePanel',
    collapseShim: 'collapseShim'
};

// Need the static URL for absolute addresses
//var GEE_STATIC_URL = window.location.protocol + '//' + window.location.host;
// Static image paths in this example are relative to the earth server host.
var GEE_EARTH_IMAGE_PATH = FUSION_MAP_SERVER + '/earth/images/';
var GEE_MAPS_IMAGE_PATH = FUSION_MAP_SERVER + '/maps/mapfiles/';

// Search Timeout specifies how long to wait (in milliseconds) before
// determining the search failed.
// override with '?search_timeout=xxx' on the URL where xxx is in milliseconds.
var geeSearchTimeout = 5000;  // 5 seconds seems OK

// Initial view parameters are overrideable from the html or the url.
// Override initial lat lng with '?ll=32.898,-100.30' on the URL.
// Override initial zoom level with '?z=8' on URL
var geeInitialViewLat = 37.5432;
var geeInitialViewLon = -96.2659;
var geeInitialZoomLevel = 16;

// Default Altitude for panning, keep camera at a high enough level to see
// continents.
var DEFAULT_SINGLE_CLICK_ZOOM_LEVEL = 10;  // City Level.
var DEFAULT_DOUBLE_CLICK_ZOOM_LEVEL = 14;  // Neighborhood level.
var DEFAULT_PAN_TO_ALTITUDE_METERS = 400000;
var DEFAULT_BALLOON_MAX_WIDTH_PIXELS = 500;
// We cache a map of Maps Zoom Levels (0..32) to Earth camera altitudes.
var geeZoomLevelToCameraAltitudeMap = null;
var geeIconUrls = {};  // Cache of frequently used URLs.

// We need to cache some information to manage network link layers for the
// earth plugin.
var geIsNetworkLink = {};  // Keep track of whether each layer is a network link
                           // or not. layerId: boolean
var geNetworkLinks = {};  // Keep track of the network links KmlFeature objects.
var geLoadedNetworkLinks = {};  // Keep track of the loaded network links.
var geeFolderLayerChildren = {};  // Keep track of the layer id's of the
                                  // children of layer folders.
var geeSupplementalLayerInfo = {};  // Index for additional layer info that is
                                    // not accessible via the GE Plugin API.
var LogoOverlay; // = ge.createScreenOverlay('');
var isMouseDown = false;
var measureLineStringPlacemark = null;
var lineStringPlacemark = null;
var measurePolygonPlacemark = null;
var pointCount = 0;
var doc = null;
var startLat;
var startLng;
var endLat;
var endLng;
var lineString;

/**
 * Init the Google Earth plugin. This will contact the GEE Server for the GEE
 * Database specifics and will use those to initialize: 1) the earth plugin 2)
 * the layer panel 3) the search tabs
 */
function geeInit() {
  // check that geeServerDefs are loaded.
  if (geeServerDefs == undefined) {
    alert('Error: The Google Earth Enterprise server does not recognize the ' +
          'requested database.');
    return;
  }
  // Init some globals that require other JS modules to be loaded.
  geeZoomLevelToCameraAltitudeMap = zoomLevelToAltitudeMap();
  // Cache the folder icon URLs.
  geeIconUrls = {
      openedFolder: geeEarthImage('openfolder.png'),
      closedFolder: geeEarthImage('closedfolder.png'),
      cancelButton: geeEarthImage('cancel.png'),
      collapse: geeMapsImage('collapse.png'),
      expand: geeMapsImage('expand.png'),
      transparent: geeMapsImage('transparent.png'),
      defaultLayerIcon: geeEarthImage('default_layer_icon.png')
  };

  // If no search tabs are defined, we have a default search tab for jumping
  // to a lat lng (without hitting the server).
  // You can also hard code handy search tab functionality here by appending
  // to the existing geeServerDefs['searchTabs'].
  if (geeServerDefs.searchTabs == '') {
    // Create a default search tab if none are defined by the server.
    geeServerDefs['searchTabs'] = geeDefaultSearchTabs();
  }

  geeInitSupplementalLayerInfo(geeServerDefs.layers);

  // --------------------------------Begin GEE specific settings
  // Required for Behind the firewall usage.
  // Enterprise specific overrides for running the Earth plugin behind
  // the firewall.
  if (!('google' in window)) { window.google = {}; }
  if (!('loader' in window.google)) { window.google.loader = {}; }
  if (!('earth' in window.google)) { window.google.earth = {}; }
  // Enterprise Earth Plugin Key
  window.google.loader.ApiKey = 'ABCDEFGHIJKLMNOPgoogle.earth.ec.key';
  window.google.loader.KeyVerified = true;
  // Turn off logging.
  window.google.earth.allowUsageLogging = false;
  // Override the default google.com error page.
  window.google.earth.setErrorUrl('/error.html');
  // Override the default loading icon.
  window.google.earth.setLoadingImageUrl(geeEarthImage('loading.gif'));
  // --------------------------------End GEE specific settings

  // **************************************************************************
  // You will need to replace yourserver.com with the appropriate server name.
  // For authentication to your database,
  // simply add arguments 'username' and 'password' to earthArgs.
  // IE6 compatibility note: no trailing commas in dictionaries or arrays.
  var earthArgs = {
    'database' : geeServerDefs['serverUrl']
  };
  if (geeServerDefs['isAuthenticated']) {
    // Pop up auth dialog if desired.
    var username = '';
    var password = '';
    earthArgs['username'] = username;
    earthArgs['password'] = password;
  }
  // We construct the internal layer container and title divs.
  // The inner container is needed globally.

  //geeInitLeftPanelDivs();  // The left panel needs some sub-divs for layers etc.
  //geeResizeDivs();  // Resize the map to fill the screen.

  google.earth.createInstance(geeDivIds.map, geeEarthPluginInitCb,
                              geeEarthPluginFailureCb, null);
}

/**
 * Initialize an indexed object geeSupplementalLayerInfo of supplemental layer
 * information provided by
 * the GEE Server.
 * @param  {Array.<Object>}
 *            layers the array of layer info.
 */
function geeInitSupplementalLayerInfo(layers) {
  for (var i = 0; i < layers.length; ++i) {
    var id = layers[i].id;
    geeSupplementalLayerInfo[id] = layers[i];
  }
}

/**
 * The Earth Plugin init callback.
 * @param {GEPlugin}
 *          object the just created Google Earth plugin object.
 */
function geeEarthPluginInitCb(object) {
  ge = object;
  ge.getOptions().setStatusBarVisibility(true);  // show lat,lon,height,eye_alt
  ge.getOptions().setScaleLegendVisibility(true);  // show scale legend
  ge.getWindow().setVisibility(true);
  ge.getNavigationControl().setVisibility(ge.VISIBILITY_SHOW);
//  ge.getNavigationControl().getScreenXY().setXUnits(ge.UNITS_PIXELS);
//  ge.getNavigationControl().getScreenXY().setYUnits(ge.UNITS_INSET_PIXELS);
  
  ge.getOptions().setGridVisibility(false);
  // Initialize the initial view (which can be overridden by URL parameters).
  var lat = initY;
  var lon = initX;
  var zoom = initLevel;
  // Process the initial view overrides.
  if (getPageURLParameter('ll')) {
    var latlng = getPageURLParameter('ll').split(',');
    if (latlng.length == 2) {
      lat = latlng[0];
      lon = latlng[1];
    }
  }
  if (getPageURLParameter('z')) {
    zoom = parseInt(getPageURLParameter('z'));
  }

  // On successful init, we can now load the layers and initialize the search
  // tabs.
  geeInitLayerList(ge, geeDivIds.layers);

  // Check for a search_timeout override.
  if (getPageURLParameter('search_timeout')) {
    geeSearchTimeout = getPageURLParameter('search_timeout');
  }
  initializeSearch(geeDivIds.searchTabs, geeServerDefs.searchTabs, geeSearchTimeout);
//  geeCreateShims();
//  geeResizeDivs();
    resizeMap();
    
    doc = ge.createDocument('');
    ge.getFeatures().appendChild(doc);
    google.earth.addEventListener(ge.getView(),"viewchangeend",geViewChanged); 
    geePanTo(lat, lon, zoom);
    if (geTour)
    {
        //Sightseeing.kmz
        //loadKml(document.location.href.substring(0, document.location.href.lastIndexOf('/')+1) + 'Cyber Security Event Linkgraph.kmz');
        //LoadTour(document.location.href.substring(0, document.location.href.lastIndexOf('/')+1) + 'Cyber Security Tour.kmz');
        LoadTour(document.location.href.substring(0, document.location.href.lastIndexOf('/')+1) + 'Sightseeing.kml');
    }
    //tmsamples.kml
    //loadKml(document.location.href.substring(0, document.location.href.lastIndexOf('/')+1) + 'tmsamples.kml');
    //loadKml(document.location.href.substring(0, document.location.href.lastIndexOf('/')+1) + 'Cyber Security Event Linkgraph.kmz');
    map = new GFusionMap(document.getElementById("hidden_map_canvas"));
    var fusionmap_elem = document.getElementById('hidden_map_canvas');
    var searchresults_elem = FindElement("search_panel");
    if (searchresults_elem)
      searchresults_docker = new SidePanel(searchresults_elem);
    var myplaces_elem = FindElement("myplaces_panel");
    if (myplaces_elem)
        myplaces_docker = new SidePanel(myplaces_elem);
    var layers_elem = FindElement("layers_panel");
    if (layers_elem)
        layers_docker = new SidePanel(layers_elem);
        
    buildBookmarks();
    //placemark_manager = new PlacemarkManager(fusionmap_elem);
    //InitializeSearch(fusionmap_elem);
    fillMeasureOptions(selectedTool);
    
    //document.getElementById('downloadGE').innerHTML = '';
    document.getElementById('downloadGE').style.visibility = "hidden";
    loadESSLogo(document.location.href.substring(0, document.location.href.lastIndexOf('/')+1) + 'images/earthspector_transparent.png');
    resizeMap();
}


function loadESSLogo(url)
{
    // Create the ScreenOverlay
    LogoOverlay = ge.createScreenOverlay('');

    // Specify a path to the image and set as the icon
    var icon = ge.createIcon('');
    icon.setHref(url);
    LogoOverlay.setIcon(icon);

    try
    {
        LogoOverlay.getOverlayXY().setXUnits(ge.UNITS_PIXELS);
        LogoOverlay.getOverlayXY().setYUnits(ge.UNITS_PIXELS);
        LogoOverlay.getOverlayXY().setX(150);
        LogoOverlay.getOverlayXY().setY(110);
    }
    catch(ex)
    {
    }
    // Set the ScreenOverlay's position in the window
//    LogoOverlay.getOverlayXY().setXUnits(ge.UNITS_FRACTION);
//    LogoOverlay.getOverlayXY().setYUnits(ge.UNITS_FRACTION);
//    LogoOverlay.getOverlayXY().setX(.15);
//    LogoOverlay.getOverlayXY().setY(0.1);
//    LogoOverlay.getOverlayXY().setXUnits(ge.UNITS_PIXELS);
//    LogoOverlay.getOverlayXY().setYUnits(ge.UNITS_PIXELS);
//    LogoOverlay.getOverlayXY().setX(newWidth-278);
//    LogoOverlay.getOverlayXY().setY(newHeight-116);

    // Specify the point in the image around which to rotate
    LogoOverlay.getRotationXY().setXUnits(ge.UNITS_FRACTION);
    LogoOverlay.getRotationXY().setYUnits(ge.UNITS_FRACTION);
    LogoOverlay.getRotationXY().setX(0);
    LogoOverlay.getRotationXY().setY(0);
    
    // Set the overlay's size in pixels
//    LogoOverlay.getSize().setXUnits(ge.UNITS_PIXELS);
//    LogoOverlay.getSize().setYUnits(ge.UNITS_PIXELS);
//    LogoOverlay.getSize().setX(278);
//    LogoOverlay.getSize().setY(116);

    // Rotate the overlay
    LogoOverlay.setRotation(0);

    // Add the ScreenOverlay to Earth
    ge.getFeatures().appendChild(LogoOverlay);
    resizeMap();
}

function LoadTour(url) {
    try
    {
        // Load the first (or tourNumber'th) <gx:Tour> in the tour's KML URL.
        google.earth.fetchKml(
            ge,
            url,
            function(kmlObject) {
                try
                {
                    if (!kmlObject) {
                        setTimeout(function() {
                            alert('Error loading KML.');
                          }, 0);
                        return;
                    }
                    ge.getNavigationControl().setVisibility(ge.VISIBILITY_HIDE);
                    ge.getFeatures().appendChild(kmlObject);

                    // Walk the loaded KML object hierarchy looking for a <gx:Tour>.
                    walkKmlDom(kmlObject, function(context) {
                        if (this.getType() == 'KmlTour') {
                            ge.getTourPlayer().setTour(this);
                            ge.getTourPlayer().play();
                            return false;
                        }
                    });

                    // Remove any existing extra KMLs folder.
                    if (currentExtraKmlsObject) {
                        ge.getFeatures().removeChild(currentExtraKmlsObject);
                        currentExtraKmlsObject = null;
                    }

                    // Load any extra KML files necessary to view this tour into a new
                    // folder.
                    var extraKmls = [];
                    var currentExtraKmlsObject = ge.createFolder('');
                    ge.getFeatures().appendChild(currentExtraKmlsObject);

                    for (var i = 0; i < extraKmls.length; i++) {
                        // Create a network link to this extra KML file
                        // and place it in the extra KMLs folder.
                        var link = ge.createLink('');
                        link.setHref(extraKmls[i]);

                        var networkLink = ge.createNetworkLink('');
                        networkLink.setLink(link);

                        currentExtraKmlsObject.getFeatures().appendChild(networkLink);
                    }
                }
                catch (ex2)
                {
                    alert(ex2);
                }
            }
        );

    }
    catch(ex)
    {
        alert(ex);
    }
}

















var g_kmlObject;
var g_treeIdObjectMap = null;
function loadKml(url) {
 
  google.earth.fetchKml(ge, url, function(kmlObject) {
      try
      {
        if (!kmlObject) {
          // show error
          setTimeout(function() {
            alert('Error loading KML.');
          }, 0);
          return;
        }
        
        if (g_kmlObject)
          ge.getFeatures().removeChild(g_kmlObject);
        
        g_kmlObject = kmlObject;
        ge.getFeatures().appendChild(g_kmlObject);
        //flyToFeature(g_kmlObject);
        
        //buildTreeUI(g_kmlObject);
      }
      catch (ex)
      {
        alert(ex);
      }
  });

}
function flyToFeature(kmlFeature) {
  var aspectRatio = dojo.coords('map_canvas').w * 1.0 / dojo.coords('map_canvas').h;
  var lookAt = computeFitLookAt(ge, kmlFeature, aspectRatio);
  if (lookAt)
    ge.getView().setAbstractView(lookAt);
}
function buildTreeUI(kmlObject) {
  delete g_treeIdObjectMap;
  g_treeIdObjectMap = {};
  
  var treeData = {
    identifier: 'id',
    label: 'name',
    items: []
  };
  
  // walk the loaded KML object DOM
  walkKmlDom(kmlObject, function(context) {
    // generate a random, unique ID for this node (Dojo requires a unique ID
    // per each node)
    var nodeId = Number(new Date()).toString() + Math.round(Math.random() * 99999).toString();
    g_treeIdObjectMap[nodeId] = this;
    
    // create the tree node for this item
    var treeNodeData = {
      id: nodeId,
      name: (this.getName() ? this.getName() : '<' + this.getType() + '>'),
      type: this.getType(),
      checked: this.getVisibility(),
      children: []
    };
    
    // add the tree node to the tree data hierarchy 
    context.current.push(treeNodeData);
    
    //alert(treeNodeData.checked);
    // all actual KML child nodes will be added to this tree node's
    // children list
    context.child = treeNodeData.children;
  }, { rootContext: treeData.items });
  
  if (dijit.byId('checkboxtree'))
    dijit.byId('checkboxtree').destroy();
  // create the Dojo tree widget
  // and set its data to the hierarchy we just
  // built using walkKmlDom
  var treeDiv = document.createElement('div');
  treeDiv.style.height = '100%';
  dojo.byId('imported_layers_panel').appendChild(treeDiv);
  //var treeDiv = document.getElementById('imported_layers_frame');
  var store = new dojo.data.ItemFileWriteStore({ data: treeData });
  
  var model = new dijit.tree.CheckboxForestStoreModel({
    store: store,
    labelAttr: 'name',
    typeAttr: 'type'
  });
  
  var checkboxtree = new dijit.CheckboxTree({
    id: 'checkboxtree',
    model: model
  }, treeDiv);

  // watch for changes in the 'checked' attribute and update feature visibility
  // accordingly
  dojo.connect(store, 'onSet', function(item, attribute, oldValue, newValue) {
    if (oldValue != newValue &&
        attribute == 'checked') {
      var kmlObject = g_treeIdObjectMap[store.getValue(item, 'id')];
      if (!kmlObject)
        return;
      
      kmlObject.setVisibility(newValue);
      if (newValue == true) {
        var c = kmlObject;
        while (c && 'setVisibility' in c) {
          c.setVisibility(newValue);
          c = c.getParentNode();
          //store.setValue(item, 'checked' 
        }
      }
    }
  });
  
  // when clicking a checkboxtree item, fly to it
  dojo.connect(checkboxtree, 'onClick', function(item) {
    if (item) {
      var kmlObject = g_treeIdObjectMap[store.getValue(item, 'id')];
      if (!kmlObject)
        return;
      
      flyToFeature(kmlObject);
    }
  });
  
  var oldGetIconClass = checkboxtree.getIconClass;
  checkboxtree.getIconClass = function(item, opened) {
    var cls = '';
    if (item) {
      var kmlObject = g_treeIdObjectMap[store.getValue(item, 'id')];
      if (kmlObject) {
        if ('getGeometry' in kmlObject && kmlObject.getGeometry()) {
          cls = kmlObject.getGeometry().getType();
        } else {
          cls = kmlObject.getType();
        }
      }
    }
    
    return cls + ' ' + oldGetIconClass.apply(checkboxtree, [item, opened]);
  };
  
  checkboxtree.getLabelClass = function(item, opened) {
    if (item && checkboxtree.model.mayHaveChildren(item)) {
      return 'folder';
    }
    
    return '';
  };
  
  expandTree();
}
 
function expandTree() {
  var checkboxtree = dijit.byId('checkboxtree');
  function expandChildNode(node) {
    dojo.forEach(node.getChildren(), function(c) { 
      checkboxtree._expandNode(c);
      expandChildNode(c);
    }, this);
  }
  
  expandChildNode(checkboxtree.rootNode);
}

//function flyToFeature(kmlFeature) {
//  var aspectRatio = dojo.coords('center').w * 1.0 / dojo.coords('center').h;
//  var lookAt = computeFitLookAt(ge, kmlFeature, aspectRatio);
//  if (lookAt)
//    ge.getView().setAbstractView(lookAt);
//}
function geViewChanged()
{
    if (!skipExtentStore)
    {
        currExtent++;
        var maxExtents = 200;
        if (currExtent > maxExtents)
        {
            currExtent = maxExtents;
            for (var i = 1; i <= maxExtents; i++)
            {
                extents[i-1] = extents[i];
            }
        }
//        var globeBounds = ge.getView().getViewportGlobeBounds();
//        var mapHeight = globeBounds.getNorth() - globeBounds.getSouth();
//        var mapWidth = globeBounds.getEast() - globeBounds.getWest();
        var camera = ge.getView().copyAsLookAt(ge.ALTITUDE_RELATIVE_TO_GROUND);
        
        extents[currExtent] = camera.getLatitude() + "," + camera.getLongitude() + "," + camera.getAltitude() + "," + camera.getHeading() + "," + camera.getTilt() + "," + camera.getRange();
        extents.splice(currExtent+1, extents.length - currExtent-1);
        
    }
    skipExtentStore = false;
}
/**
 * The Earth Plugin failure callback.
 * @param {string}
 *          message the error message.
 */
function geeEarthPluginFailureCb(message) {
//    geOn = false;
//    initialize();
  // The default behavior of the plugin will display a friendly error message.
}

var mapStartX;
var mapStartY;
var draggingOn = false;
var polyPoints = [];
var dblClicked = false;
var polygon;
var outer;

function ongeclick(event) {
    if (selectedTool == "point")
    {
        try
        {
            ge.getFeatures().removeChild(measurePlacemark); 
        }
        catch (ex)
        {
        }
        measurePlacemark = ge.createPlacemark('');
        measurePlacemark.setName("");
        ge.getFeatures().appendChild(measurePlacemark);
      
        // Create point
        var point = ge.createPoint('');
        point.setLatitude(event.getLatitude());
        point.setLongitude(event.getLongitude());
        measurePlacemark.setGeometry(point);
        calcPoint(event.getLongitude(), event.getLatitude());
    }
    else
    {
        if (draggingOn)
        {
            polyPoints.push(event);
            lineString.getCoordinates().clear();
            for (var i = 0; i < polyPoints.length; i++)
            {
                lineString.getCoordinates().pushLatLngAlt(polyPoints[i].getLatitude(), polyPoints[i].getLongitude(), 0);
            }
            lineString.getCoordinates().pushLatLngAlt(polyPoints[0].getLatitude(), polyPoints[0].getLongitude(), 0);
            if (polyPoints.length > 2 && selectedTool == "polygon")
            {
                outer.getCoordinates().clear();
                for (var i = 0; i < polyPoints.length; i++)
                {
                    outer.getCoordinates().pushLatLngAlt(polyPoints[i].getLatitude(), polyPoints[i].getLongitude(), 0);
                }
                outer.getCoordinates().pushLatLngAlt(polyPoints[0].getLatitude(), polyPoints[0].getLongitude(), 0);
            }
        }
        else
        {
            if (!dblClicked)
            {
                try
                {
                    draggingOn = true;
                    try
                    {
                        ge.getFeatures().removeChild(measureLineStringPlacemark);
                    }
                    catch (ex)
                    {
                    }
                    try
                    {
                        ge.getFeatures().removeChild(lineStringPlacemark);
                    }
                    catch (ex)
                    {
                    }
                    try
                    {
                        ge.getFeatures().removeChild(measurePolygonPlacemark);
                    }
                    catch (ex)
                    {
                    }
                    if (activatedTool == 'measure')
                    {
                        measureLineStringPlacemark = ge.createPlacemark('');
                        measurePolygonPlacemark = ge.createPlacemark('');
                        
                        lineString = ge.createLineString('');
                        measureLineStringPlacemark.setGeometry(lineString);
                        lineString.setTessellate(true);
                        lineString.setAltitudeMode(ge.ALTITUDE_CLAMP_TO_GROUND);
                     
                        measureLineStringPlacemark.setStyleSelector(ge.createStyle(''));
                        var lineStyle = measureLineStringPlacemark.getStyleSelector().getLineStyle();
                        lineStyle.setWidth(4);
                        lineStyle.getColor().set('660000ff');  // aabbggrr formatx
                        if (selectedTool == "polygon") 
                        {
                            polygon = ge.createPolygon('');
                            outer = ge.createLinearRing('');
                            polygon.setOuterBoundary(outer);
                            measurePolygonPlacemark.setGeometry(polygon);
                            measurePolygonPlacemark.setStyleSelector(ge.createStyle(''));
                            var lineStyle2 = measurePolygonPlacemark.getStyleSelector().getLineStyle();
                            lineStyle2.setWidth(4);
                            lineStyle2.getColor().set('660000ff'); 
                            var polyStyle = measurePolygonPlacemark.getStyleSelector().getPolyStyle();
                            polyStyle.getColor().set('66000000');  // aabbggrr format
                        }
                        
                        polyPoints.push(event);

                        lineString.getCoordinates().pushLatLngAlt(event.getLatitude(), event.getLongitude(), 0);
                        if (selectedTool == "polygon") 
                        {
                            outer.getCoordinates().pushLatLngAlt(event.getLatitude(), event.getLongitude(), 0);
                        }
                        ge.getFeatures().appendChild(measureLineStringPlacemark);
                        ge.getFeatures().appendChild(measurePolygonPlacemark);
                    }
                    else
                    {
                        lineStringPlacemark = ge.createPlacemark('');
                        
                        lineString = ge.createLineString('');
                        lineStringPlacemark.setGeometry(lineString);
                        lineString.setTessellate(true);
                        lineString.setAltitudeMode(ge.ALTITUDE_CLAMP_TO_GROUND);
                     
                        lineStringPlacemark.setStyleSelector(ge.createStyle(''));
                        var lineStyle = lineStringPlacemark.getStyleSelector().getLineStyle();
                        lineStyle.setWidth(4);
                        lineStyle.getColor().set('660000ff');  // aabbggrr formatx
                        
                        polyPoints.push(event);

                        lineString.getCoordinates().pushLatLngAlt(event.getLatitude(), event.getLongitude(), 0);
                        if (selectedTool == "polygon") 
                        {
                            outer.getCoordinates().pushLatLngAlt(event.getLatitude(), event.getLongitude(), 0);
                        }
                        ge.getFeatures().appendChild(lineStringPlacemark);
                    }
                }
                catch (ex2)
                {
			        deneme = document.getElementById("mouseCoords");
			        deneme.innerHTML = ex2;
                }
            }
            else
            {
                dblClicked = false;
            }
        }
    }
}
function ongedblclick(event) {
    if (selectedTool != "point")
    {
        var selObj = document.getElementById('distanceSelect');
        var selIndex = selObj.selectedIndex;
	    var distanceType = selObj.options[selIndex].value;
        if (draggingOn)
        {
            lineString.getCoordinates().clear();
            for (var i = 0; i < polyPoints.length; i++)
            {
                lineString.getCoordinates().pushLatLngAlt(polyPoints[i].getLatitude(), polyPoints[i].getLongitude(), 0);
            }
            lineString.getCoordinates().pushLatLngAlt(event.getLatitude(), event.getLongitude(), 0);
            if (selectedTool == "polygon") 
            {
                lineString.getCoordinates().pushLatLngAlt(polyPoints[0].getLatitude(), polyPoints[0].getLongitude(), 0);
                outer.getCoordinates().clear();
                for (var i = 0; i < polyPoints.length; i++)
                {
                    outer.getCoordinates().pushLatLngAlt(polyPoints[i].getLatitude(), polyPoints[i].getLongitude(), 0);
                }
                outer.getCoordinates().pushLatLngAlt(event.getLatitude(), event.getLongitude(), 0);
            }
            try
            {
                var pPoints = [];
                if (selectedTool == "polygon") 
                {
                    
                    var pnt;
                    for (var i = 0; i < polyPoints.length; i++)
                    {
                        pnt = new GLatLng(polyPoints[i].getLatitude(), polyPoints[i].getLongitude());
                        pPoints.push(pnt);
                    }
                    pnt = new GLatLng(polyPoints[0].getLatitude(), polyPoints[0].getLongitude());
                    pPoints.push(pnt);
                    polyShapeY = new GPolyline(pPoints, lineColor, 5, opacity);
                    var length = polyShapeY.getLength()/1000;
                    length = convertTo(length, distanceType, "Kilometers");
                    var lineStyle;
                    if (activatedTool == "measure")
                        lineStyle = measureLineStringPlacemark.getStyleSelector().getLineStyle();
                    else
                        lineStyle = lineStringPlacemark.getStyleSelector().getLineStyle();
                        
                    lineStyle.setWidth(4);
                    lineStyle.getColor().set('66000000');  // aabbggrr formatx

                    var lineStyle2 = measurePolygonPlacemark.getStyleSelector().getLineStyle();
                    lineStyle2.setWidth(4);
                    lineStyle2.getColor().set('66000000'); 
                    polyShapeX = new GPolygon(pPoints, lineColor, 5, opacity, "#000000", opacity);
                    var area = polyShapeX.getArea();
	                area = convertAreaTo(area, distanceType);
                    var square = "";
                    if (distanceType != "Hectares" && distanceType != "Ares" && distanceType != "Acres")
                        square = "Square ";
                    document.getElementById('measureresults').innerHTML = "Area: " + area + " " + square + distanceType + "<br /><br />Length: " + length + " " + distanceType;
                }
                else if (selectedTool == "line") 
                {
                    var pnt;
                    for (var i = 0; i < polyPoints.length; i++)
                    {
                        pnt = new GLatLng(polyPoints[i].getLatitude(), polyPoints[i].getLongitude());
                        pPoints.push(pnt);
                    }
                    var lineStyle;
                    if (activatedTool == "measure")
                        lineStyle = measureLineStringPlacemark.getStyleSelector().getLineStyle();
                    else
                        lineStyle = lineStringPlacemark.getStyleSelector().getLineStyle();
                        
                    lineStyle.setWidth(4);
                    lineStyle.getColor().set('66000000');  // aabbggrr formatx
                    var polyShapeY = new GPolyline(pPoints, lineColor, 3, opacity);
                    var length = polyShapeY.getLength()/1000;
                    length = convertTo(length, distanceType, "Kilometers");
                    document.getElementById('measureresults').innerHTML = length + " " + distanceType;
                }   
                googlePoints = pPoints;
            }
            catch (ex)
            {
			    deneme = document.getElementById("mouseCoords");
			    deneme.innerHTML = ex;
            }
            draggingOn = false;
            dblClicked = true;
            setTimeout (function() {polyPoints = [];}, 500);
            
        }
    }
    return false;
}
function ongemeasuremousemove(event) {
    if (selectedTool != "point")
    {
        if (draggingOn)
        {
            try
            {
                lineString.getCoordinates().clear();
                for (var i = 0; i < polyPoints.length; i++)
                {
                    lineString.getCoordinates().pushLatLngAlt(polyPoints[i].getLatitude(), polyPoints[i].getLongitude(), 0);
                }
                lineString.getCoordinates().pushLatLngAlt(event.getLatitude(), event.getLongitude(), 0);
            }
            catch (ex)
            {
			    deneme = document.getElementById("mouseCoords");
			    deneme.innerHTML = ex;
            }
        }
    }
    return false;
}
function ongemousemove(event) {
  if (isMouseDown) {
    lineString.getCoordinates().clear();
    lineString.getCoordinates().pushLatLngAlt(startLat, startLng, 0);
    lineString.getCoordinates().pushLatLngAlt(startLat, event.getLongitude(), 0);
    lineString.getCoordinates().pushLatLngAlt(event.getLatitude(), event.getLongitude(), 0);
    lineString.getCoordinates().pushLatLngAlt(event.getLatitude(), startLng, 0);
    lineString.getCoordinates().pushLatLngAlt(startLat, startLng, 0);
  }
}
function ongemousedown(event) {
    try {
        if (isMouseDown)
        {
            if (activatedTool == 'zoomin')
                zoomIn(startLat, startLng, event.getLatitude(), event.getLongitude());
            else if (activatedTool == 'zoomout')
                zoomOut(startLat, startLng, event.getLatitude(), event.getLongitude());
            else if (activatedTool == 'identify')
                identifyCall(startLat, startLng, event.getLatitude(), event.getLongitude());
        }
        else
        {
            isMouseDown = true;
            
            if (activatedTool == "measure")
            {
                measureLineStringPlacemark = ge.createPlacemark('');
                lineString = ge.createLineString('');
                measureLineStringPlacemark.setGeometry(lineString);
                lineString.setTessellate(true);
                lineString.setAltitudeMode(ge.ALTITUDE_CLAMP_TO_GROUND);
             
                measureLineStringPlacemark.setStyleSelector(ge.createStyle(''));
                var lineStyle = measureLineStringPlacemark.getStyleSelector().getLineStyle();
                lineStyle.setWidth(4);
                lineStyle.getColor().set('660000ff');  // aabbggrr formatx

                startLat = event.getLatitude();
                startLng = event.getLongitude();

                lineString.getCoordinates().pushLatLngAlt(event.getLatitude(), event.getLongitude(), 0);
             
                doc.getFeatures().appendChild(measureLineStringPlacemark);            
            }
            else
            {
                lineStringPlacemark = ge.createPlacemark('');
                lineString = ge.createLineString('');
                lineStringPlacemark.setGeometry(lineString);
                lineString.setTessellate(true);
                lineString.setAltitudeMode(ge.ALTITUDE_CLAMP_TO_GROUND);
             
                lineStringPlacemark.setStyleSelector(ge.createStyle(''));
                var lineStyle = lineStringPlacemark.getStyleSelector().getLineStyle();
                lineStyle.setWidth(4);
                lineStyle.getColor().set('660000ff');  // aabbggrr formatx

                startLat = event.getLatitude();
                startLng = event.getLongitude();

                lineString.getCoordinates().pushLatLngAlt(event.getLatitude(), event.getLongitude(), 0);
             
                doc.getFeatures().appendChild(lineStringPlacemark);     
            }

        }
        
    }
    catch (Err)
    {
    }
}


function ongemouseup(event) {
    lineString.getCoordinates().clear();
    lineString.getCoordinates().pushLatLngAlt(startLat, startLng, 0);
    lineString.getCoordinates().pushLatLngAlt(startLat, event.getLongitude(), 0);
    lineString.getCoordinates().pushLatLngAlt(event.getLatitude(), event.getLongitude(), 0);
    lineString.getCoordinates().pushLatLngAlt(event.getLatitude(), startLng, 0);
    lineString.getCoordinates().pushLatLngAlt(startLat, startLng, 0);
    if (activatedTool == "measure")
        setTimeout (function() {doc.getFeatures().removeChild(measureLineStringPlacemark)}, 10);
    else
        setTimeout (function() {doc.getFeatures().removeChild(lineStringPlacemark)}, 10);
    
    if (activatedTool == 'zoomin')
        zoomIn(startLat, startLng, event.getLatitude(), event.getLongitude());
    else if (activatedTool == 'zoomout')
        zoomOut(startLat, startLng, event.getLatitude(), event.getLongitude());
    else if (activatedTool == 'identify')
        identifyCall(startLat, startLng, event.getLatitude(), event.getLongitude());
}

function identifyCall(startLat, startLng, endLat, endLng)
{
    isMouseDown = false;
    var nwpx = new GLatLng(startLat, startLng);
    var nepx = new GLatLng(startLat, endLng);
    var sepx = new GLatLng(endLat, endLng);
    var swpx = new GLatLng(endLat, startLng);
    var identifyAreaPoly = new GPolyline([nwpx, nepx, sepx, swpx, nwpx], "000000", 2,.4);
    polyBounds = identifyAreaPoly.getBounds();
    var ne = polyBounds.getNorthEast();
    var sw = polyBounds.getSouthWest();
    var se = new GLatLng(sw.lat(), ne.lng());
    var nw = new GLatLng(ne.lat(), sw.lng());
    identifyLevel = map.getBoundsZoomLevel(polyBounds);

    var pl = new SOAPClientParameters();
    pl.add("nelat", ne.lat());
    pl.add("nelng", ne.lng());
    pl.add("selat", sw.lat());
    pl.add("selng", ne.lng());
    pl.add("swlat", sw.lat());
    pl.add("swlng", sw.lng());
    pl.add("nwlat", ne.lat());
    pl.add("nwlng", sw.lng());
    pl.add("TableNames", document.getElementById('idLayerList').options[document.getElementById('idLayerList').selectedIndex].value);
    var url = document.location.href.substring(0, document.location.href.lastIndexOf('/')+1) + "Service.asmx";
    SOAPClient.invoke(url, "GetData", pl, true, GetData_callBack);
    loadingData();
}

function zoomIn(startLat, startLng, endLat, endLng)
{
    isMouseDown = false;
    var nwpx = new GLatLng(startLat, startLng);
    var nepx = new GLatLng(startLat, endLng);
    var sepx = new GLatLng(endLat, endLng);
    var swpx = new GLatLng(endLat, startLng);
    var zoomAreaPoly = new GPolyline([nwpx, nepx, sepx, swpx, nwpx], "000000", 2,.4);
    polyBounds = zoomAreaPoly.getBounds();
    var ne = polyBounds.getNorthEast();
    var sw = polyBounds.getSouthWest();
    var se = new GLatLng(sw.lat(), ne.lng());
    var nw = new GLatLng(ne.lat(), sw.lng());
    zoomLevel = map.getBoundsZoomLevel(polyBounds);
    center = polyBounds.getCenter();
    if (sw.lat() != ne.lat() || sw.lng() != ne.lng())
        geePanTo(center.lat(), center.lng(), zoomLevel+6);
}

function zoomOut(startLat, startLng, endLat, endLng)
{
    isMouseDown = false;
    try
    {
        var nwpx = new GLatLng(startLat, startLng);
        var nepx = new GLatLng(startLat, endLng);
        var sepx = new GLatLng(endLat, endLng);
        var swpx = new GLatLng(endLat, startLng);
        var zoomAreaPoly = new GPolyline([nwpx, nepx, sepx, swpx, nwpx], "000000", 2,.4);
        var globeBounds = ge.getView().getViewportGlobeBounds();
        var mapHeight = globeBounds.getNorth() - globeBounds.getSouth();
        var mapWidth = globeBounds.getEast() - globeBounds.getWest();

        polyBounds = zoomAreaPoly.getBounds();
        var ne = polyBounds.getNorthEast();
        var sw = polyBounds.getSouthWest();
        var polyHeight = ne.lat() - sw.lat();
        var polyWidth = ne.lng() - sw.lng();

        var heightPerc = 1 - (polyHeight / mapHeight);
        var widthPerc = 1 - (polyWidth / mapWidth);  
        var newHeight = ((mapHeight * heightPerc) + mapHeight) / 2;
        var newWidth = ((mapWidth * widthPerc) + mapWidth) / 2;
        
        var newNE = new GLatLng(globeBounds.getNorth()+newHeight, globeBounds.getEast()+newWidth);
        var newSW = new GLatLng(globeBounds.getSouth()-newHeight, globeBounds.getWest()-newWidth);
        var measurePoly = new GLatLngBounds(newSW, newNE);
        
        var se = new GLatLng(sw.lat(), ne.lng());
        var nw = new GLatLng(ne.lat(), sw.lng());
        zoomLevel = map.getBoundsZoomLevel(measurePoly);
        center = polyBounds.getCenter();
        if (sw.lat() != ne.lat() || sw.lng() != ne.lng())
            geePanTo(center.lat(), center.lng(), zoomLevel+3);
    }
    catch (ex)
    {
        alert(ex);
    }

}
/**
 * Fill in the LayerDiv with a list of checkboxes for the layers from the
 * current Google Earth Database. Each checkbox refers to a geeToggleLayer
 * callback.
 * @param {GEPlugin}
 *          earth the earth plugin object.
 * @param {string}
 *          layerDivId the div id of the layer panel.
 */
function geeInitLayerList(earth, layerDivId) {
  var rootLayer = earth.getLayerRoot();
  var layerDiv = document.getElementById(layerDivId);
  var features = rootLayer.getFeatures();
  var childLayers = features.getChildNodes();
  var layerList = createElement(layerDiv, 'ul');
  layerList.className = 'layer_list';
  var rootLayerId = 'root';
  geeFolderLayerChildren[rootLayerId] = [];  // Init the array for each folder.
  try
  {
    geeCreateLayerElements(rootLayerId, layerList, childLayers);
  }
  catch (err)
  {
  }
  try
  {
    var layers = getLayerNames(rootLayerId, childLayers, false);
    var visibleLayers = getLayerNames(rootLayerId, childLayers, true);
    //alert(layers.length);
    try
    {
        var visLayers = "";
        for (var lyr = 0; lyr < visibleLayers.length; ++lyr) 
        {
            visLayers += visibleLayers[lyr] + ",";
        }
        addLayerToIdList("Visible Layers", visLayers);
    }
    catch (ex2)
    {
    }
    try
    {
        var allLayers = "";
        for (var lyr = 0; lyr < layers.length; ++lyr) {
            allLayers += layers[lyr] + ",";
        }
        
        addLayerToIdList("All Layers", allLayers);
    }
    catch (ex2)
    {
    }

  }
  catch (ex)
  {
    //alert(ex);
  }
  try
  {
    getLayerName(rootLayerId, childLayers);
  }
  catch (ex)
  {
  }
  try
  {
    document.getElementById(bordercheckBoxId).checked = true;
    geeToggleLayer(null, bordercheckBoxId, borderlayerId, borderlayerName);
  }
  catch (ex)
  {
  }
}

function getLayerNames(parentFeatureId, childLayers, visibleOnly)
{
  var layers = [];
  for (var i = 0; i < childLayers.getLength(); ++i) {
    var feature = childLayers.item(i);
    var layerId = feature.getId();
    var layerName = feature.getName();
    var isVisible = false;
    if (feature.getVisibility()) {
      isVisible = true;
    }
    var type = feature.getType();
    var isOpenable = (layerId in geeSupplementalLayerInfo) ? geeSupplementalLayerInfo[layerId].isExpandable : true;
    
    if (type == 'KmlFolder' && isOpenable) 
    {
        if (layerName != "Locations")
        {
            var features = feature.getFeatures();
            var folderChildLayers = features.getChildNodes();
            var layers2 = getLayerNames(layerId, folderChildLayers, visibleOnly);
            for (var j = 0; j< layers2.length; j++)
            {
                layers.push(layers2[j]);
            }
        }
    }
    else
    {
        if (layerName != "Imagery" && layerName != "Terrain")
        {
            if (visibleOnly)
            {
                if (isVisible)
                    layers.push(layerName);
            }
            else
                layers.push(layerName);
        }
    }
  }
  return layers;
}

function getLayerName(parentFeatureId, childLayers)
{
  for (var i = 0; i < childLayers.getLength(); ++i) {
    var feature = childLayers.item(i);
    var layerId = feature.getId();
    var layerName = feature.getName();
    var isVisible = false;
    if (feature.getVisibility()) {
      isVisible = true;
    }
    var type = feature.getType();
    var isOpenable = (layerId in geeSupplementalLayerInfo) ? geeSupplementalLayerInfo[layerId].isExpandable : true;
    
    if (type == 'KmlFolder' && isOpenable) 
    {
        if (layerName != "Locations")
        {
            var features = feature.getFeatures();
            var folderChildLayers = features.getChildNodes();
            getLayerName(layerId, folderChildLayers);
        }
    }
    else
    {
        if (layerName != "Imagery" && layerName != "Terrain")
        {
            try
            {
                addLayerToIdList(layerName, layerName);
            }
            catch (ex)
            {
            }
            try
            {
                addLayerToQueryList(layerName, layerName);
            }
            catch (ex)
            {
            }
        }
    }
  }
}

/**
 * Fill in the given list with list items for each child layer/folder. This is a
 * recursive call to handle folders of folders.
 * @param {string}
 *          parentFeatureId the GE feature id of the parent layer folder.
 * @param {Element}
 *          parentList the DOM list element to add these layers to.
 * @param {Array}
 *          childLayers the child layers to be added to this list element.
 */
function geeCreateLayerElements(parentFeatureId, parentList, childLayers) {


//addLayerToIdList("Visible Layers", visLayers);
//addLayerToIdList("All Layers", allLayers);

//addLayerToIdList(map.getFusionLayerName(lyr), map.getFusionLayerName(lyr));
//addLayerToQueryList(map.getFusionLayerName(lyr), map.getFusionLayerName(lyr));


  for (var i = 0; i < childLayers.getLength(); ++i) {
    var feature = childLayers.item(i);
    var layerId = feature.getId();
    var layerName = feature.getName();
    var isVisible = false;
    if (feature.getVisibility()) {
      isVisible = true;
    }
    var type = feature.getType();
    // This is a setting that can be set in GEE Fusion but is not exposed
    // by the GE Plugin API.
    var isOpenable = (layerId in geeSupplementalLayerInfo) ?
                        geeSupplementalLayerInfo[layerId].isExpandable : true;
    if (!layerId) {
      // KmlLayers sometimes do not have a feature ID due to a plugin bug!!!
      layerId = parentFeatureId + '_' + i;
    }
    if (layerName == "Borders and Labels")
    {
        borderlayerId = layerId;
        borderlayerName = "Borders and Labels";
    }
    // We need to track the children of each parent folder so we can turn on
    // and off entire folders.
    geeFolderLayerChildren[parentFeatureId].push(layerId);
    var item = geeCreateLayerItem(parentList, feature, layerId, isVisible, isOpenable);

    if (type == 'KmlLayer') {
      // Do nothing.
    } else if (type == 'KmlFolder' && isOpenable) {
      // It's an openable folder. Create a sublist.
      var features = feature.getFeatures();
      var folderChildLayers = features.getChildNodes();
      geeFolderLayerChildren[layerId] = [];  // Init the array for this folder.

      // Create a sublist for the children.
      var folderListId = 'folder_contents_' + layerId;
      var folderList = createElement(item, 'ul', folderListId);
      folderList.className = 'layer_list';
      geeCreateLayerElements(layerId, folderList, folderChildLayers);

      // Hide/show child folders on click...and swap the folder icon!
      item.onclick = function(theFolder, theList, theFolderName, openFolderIconUrl, closedFolderIconUrl) {
        return function(e) {
          var iconId = theFolderName + '_icon';
          var iconElement = document.getElementById(iconId);
          var iconUrl = openFolderIconUrl;
          if (theList.style.display != 'none') {
            theList.style.display = 'none';
            iconUrl = closedFolderIconUrl;
          } else {
            theList.style.display = 'block';
          }
          iconElement.innerHTML = '<image src="' + iconUrl + '" \>';
          cancelEvent(e);
        };
      }(item, folderList, layerName, geeIconUrls.openedFolder,
          geeIconUrls.closedFolder);
      try
      {
        var iconId = layerName + '_icon';
        var iconElement = document.getElementById(iconId);
        var iconUrl = geeIconUrls.openedFolder;
        if (folderList.style.display != 'none') {
          folderList.style.display = 'none';
          iconUrl = geeIconUrls.closedFolder;
        } else {
          folderList.style.display = 'block';
        }
        iconElement.innerHTML = '<image src="' + iconUrl + '" \>';
      }
      catch (ex)
      {
      }
    }
  }
}

/**
 * Create a single layer item entry with a checkbox and appropriate hover and
 * click behaviors.
 * @param {Element}
 *          layerList the list element container for the item being created.
 * @param {KmlLayer}
 *          layer the layer object.
 * @param {string}
 *          layerId the layer object.
 * @param {boolean}
 *          isChecked true if the layer is default on.
 * @param {boolean}
 *          isOpenable true if the layer is allowed to open/expand (only
 *                     meaningful for folders.
 * @return {Element} the list item for the layer.
 */
function geeCreateLayerItem(layerList, layer, layerId,
                            isChecked, isOpenable) {
  var type = layer.getType();
  var layerName = layer.getName();
  var checkboxId = 'checkbox_' + layerId;
  if (layerName == "Borders and Labels")
  {
      bordercheckBoxId = checkboxId;
  }
  var layerIconUrl = geeFeatureIconUrl(layer);

  if ((type == 'KmlFolder') && isOpenable) {  // Give folders a 'folder icon'.
    layerIconUrl = geeIconUrls.openedFolder;
  }

  // Handle network links specially. They are loaded on demand and the
  // layer id will swap out from under us when they are loaded.
  geIsNetworkLink[layerId] = false;
  if (type == 'KmlNetworkLink') {
    geNetworkLinks[layerId] = layer;
    geIsNetworkLink[layerId] = true;
  } else if (type == 'KmlDocument') {
    // KmlDocument is a network link that's already loaded!
    geIsNetworkLink[layerId] = true;
    geNetworkLinks[layerId] = layer;
    geLoadedNetworkLinks[layerId] = { childObject: layer };
  }

  // Create the list item for the layer.
  var item = geeCreateLayerItemBasic(layerList, layerId, layerName,
                                     layerIconUrl, isChecked, 'geeToggleLayer');

  // Set to zoom in on layer on click
  item.onclick = function(layerObject) {
    return function(e) {
      var view = layerObject.getAbstractView();
      if (view) {
        ge.getView().setAbstractView(view);
      }
      cancelEvent(e);
    };
  }(layer);

  return item;
}

/**
 * Toggle the visibility of the specified layer. Assumes the 'ge',
 * 'geNetworkLinks', 'geIsNetworkLink', and 'geLoadedNetworkLinks' objects
 * are initialized.
 * @param {Object}
 *          e  the event argument.
 * @param {string}
 *          checkBoxId the name of the checkbox which maintains the layer's
 *          visibility state.
 * @param {string}
 *          layerId the id of the layer to toggle.
 * @param {string}
 *          layerName the name of the layer to toggle only used for printing
 *          error message.
 */
function geeToggleLayer(e, checkBoxId, layerId, layerName) {
    
    
  

    
    
    
    
    
    
    
    
    
    
    
    
    var isChecked = document.getElementById(checkBoxId).checked;
  try {
    var rootLayer = ge.getLayerRoot();
    var cb = document.getElementById(checkBoxId);
    try {
      var isEnabled = true;
      if (!cb.checked)
        isEnabled = false;
      // We have to handle network links separately.
      // They are loaded on demand.
      if (geIsNetworkLink[layerId]) {
        var feature = geNetworkLinks[layerId];
        if (feature.getType() == 'KmlNetworkLink') {
          // Load up a new network link and replace the array entry with
          // the KmlObject.
          try {
            // Pull out the URL for the network link.
            var link = feature.getLink();
            var href = link.getHref();
            if (geLoadedNetworkLinks[layerId]) {
              if (geLoadedNetworkLinks[layerId].childObject) {
                geLoadedNetworkLinks[layerId].childObject.setVisibility(
                  isEnabled);
              }
            } else {  // Need to load the network link.
              geLoadedNetworkLinks[layerId] = { childObject: null };
              // Fetch the KML and add a callback to record the KML object for
              // future toggling.
              window.google.earth.fetchKml(ge,
                href,
                function(obj) {
                  geLoadedNetworkLinks[layerId].childObject = obj;
                  ge.getFeatures().appendChild(obj);
                  // Update the checkbox with the new name.
                  var spanId = layerId + '_name';
                  var span = document.getElementById(spanId);
                  if (span) {
                    span.innerHTML = obj.getName();
                  }
                });
            }
          } catch (err3) {
            alert('Failed attempt to enable/disable network link: ' +
                  layerName + '\n' + err3);
          }
        }
      } else {  // A normal streamed layer.
        rootLayer.enableLayerById(layerId, isEnabled);
        // For folders, we need to update the checkboxes of all children
        geeSetFolderLayersVisibility(layerId, isEnabled);
      }
    } catch (err2) {
      alert('Failed attempt to enable/disable layer: ' + layerName +
            '\n' + err2);
    }
  } catch (err) {
    alert('Failed attempt to get checkbox for layer: ' + layerName +
          '\n' + err);
  }
  
  try
  {
      var rootLayer = ge.getLayerRoot();
      var features = rootLayer.getFeatures();
      var childLayers = features.getChildNodes();
      var rootLayerId = 'root';
    var visibleLayers = getLayerNames(rootLayerId, childLayers, true);
    try
    {
        var elSel = document.getElementById('idLayerList');
        var selIdx = elSel.selectedIndex;
        
        var visLayers = "";
        for (var lyr = 0; lyr < visibleLayers.length; ++lyr) {
            visLayers += visibleLayers[lyr] + ",";
        }
        
        elSel.remove(0);
        var elOptNew = document.createElement('option');
        elOptNew.text = "Visible Layers";
        elOptNew.value = visLayers;
        var elOptOld = elSel.options[0];  
        try 
        {
          elSel.add(elOptNew, elOptOld); // standards compliant; doesn't work in IE
        }
        catch(ex) 
        {
          elSel.add(elOptNew, 0); // IE only
        }
        
        
        //addLayerToIdList("Visible Layers", visLayers);
    }
    catch (ex2)
    {
        //alert(ex2);
    }
  }
  catch (ex)
  {
    alert(ex);
  }
  
  cancelEvent(e);
  
  setTimeout (function() {document.getElementById(checkBoxId).checked = isChecked;}, 150);
}

 /**
  * Recursively update the checkbox status for all children of the specified
  * layer (i.e., all the child layers of a folder layer).
  * @param {string}
  *             layerId  the id of the layer. If it's not a folder,
  *             it is ignored.
  * @param {boolean}
  *             isEnabled whether to set the children checkboxes as checked.
  */
function geeSetFolderLayersVisibility(layerId, isEnabled) {
  if (layerId in geeFolderLayerChildren) {
    var childLayerIds = geeFolderLayerChildren[layerId];
    for (var i = 0; i < childLayerIds.length; ++i) {
      var childLayerId = childLayerIds[i];
      var checkboxId = 'checkbox_' + childLayerId;
      var cb = document.getElementById(checkboxId);
      cb.checked = isEnabled;
      geeSetFolderLayersVisibility(childLayerId, isEnabled);
    }
  }
}

/**
 * Extract the predefined icon from the KmlFeature.
 * This is not trivial.
 * @param {KmlFeature}
 *          feature the kml feature object.
 * @return {string} the kml feature object.
 */
function geeFeatureIconUrl(feature) {
  try
  {
      var kml = feature.getKml();
      if (!kml) {
        return geeIconUrls.defaultLayerIcon;
      }
      // Pull the substring between <ItemIcon> and </ItemIcon>.
      var itemIconText = extractElementFromXml(kml, 'ItemIcon');
      // From that pull the contents between the href.
      var href = extractElementFromXml(itemIconText, 'href');
    return href;
  }
  catch (ex)
  {
    return "";
  }
}

/*
 * Interface for search_tab.js: The following code implements the GEE Methods
 * required by search_tabs.js.
 */

/**
 * Create a balloon with no content.
 * @return {KmlFeatureBalloon} the kml balloon object.
 */
function geeCreateBalloon() {
  var balloon = ge.createFeatureBalloon('');
  balloon.setMaxWidth(DEFAULT_BALLOON_MAX_WIDTH_PIXELS);
  return balloon;
}

/**
 * Create a placemark at the specified location.
 * @param {string}
 *          name the name of the placemark.
 * @param {string}
 *          description the description of the placemark.
 * @param {Object}
 *          latlng an object that contains the 'lat' and 'lon' of
 *          the position of the placemark.
 * @param {string}
 *          iconUrl the URL of the placemark's icon.
 * @param {KmlFeatureBalloon}
 *          balloon the balloon for the placemark.
 * @return {KmlPlacemark} the placemark object.
 */
function geeCreateMarker(name, description, latlng, iconUrl, balloon) {
  // Create icon style for the placemark
  var icon = ge.createIcon('');
  icon.setHref(iconUrl);
  var style = ge.createStyle('');
  style.getIconStyle().setIcon(icon);

  // create a point geometry
  var point = ge.createPoint('');
  point.setLatitude(parseFloat(latlng.lat));
  point.setLongitude(parseFloat(latlng.lon));

  // create the point placemark and add it to Earth
  var pointPlacemark = ge.createPlacemark('');
  pointPlacemark.setName(name);
  pointPlacemark.setGeometry(point);
  pointPlacemark.setStyleSelector(style);
  pointPlacemark.setDescription(description);

  // Init the balloon.
  balloon.setFeature(pointPlacemark);

  return pointPlacemark;
}

/**
 * Add the specified feature to the earth viewer.
 * @param {KmlFeature}
 *          feature the feature to add.
 */
function geeAddOverlay(feature) {
  ge.getFeatures().appendChild(feature);
}

/**
 * Remove the specified feature from the earth viewer.
 * @param {KmlFeature}
 *          feature the feature to remove.
 */
function geeRemoveOverlay(feature) {
  ge.getFeatures().removeChild(feature);
}

/**
 * Close the open info windows. This is a no-op for the earth plugin.
 */
function geeCloseInfoWindow() {
  // For Earth, do nothing.
}

/**
 * Pan and Zoom the Earth viewer to the specified lat, lng and zoom level.
 * @param {string}
 *          lat the latitude of the position to pan to.
 * @param {string}
 *          lng the longitude of the position to pan to.
 * @param {number}
 *          zoomLevel [optional] the zoom level (an integer between 1 : zoomed
 *          out all the way, and 32: zoomed in all the way) indicating the zoom
 *          level for the view.
 */
function geePanTo(lat, lng, zoomLevel) {
  lat = parseFloat(lat);
  lng = parseFloat(lng);
  var la = ge.createLookAt('');
  if (zoomLevel == null) {
    zoomLevel = DEFAULT_SINGLE_CLICK_ZOOM_LEVEL;
  }

  la.set(lat, lng, 100, ge.ALTITUDE_RELATIVE_TO_GROUND, 0, 0,
         geeZoomLevelToCameraAltitudeMap[zoomLevel]);
  ge.getView().setAbstractView(la);
}

function geePanToAltitude(lat, lng, altitude, heading, tilt, range) {
    lat = parseFloat(lat);
    lng = parseFloat(lng);
    heading = parseFloat(heading);
    tilt = parseFloat(tilt);
    altitude = parseFloat(altitude);
    range = parseFloat(range);
    var la = ge.createLookAt('');
    try
    {
        //set (double latitude, double longitude, double altitude, KmlAltitudeModeEnum altitudeMode, double heading, double tilt, double range)
        if (range == 0)
            range = altitude;
        la.set(lat, lng, altitude, ge.ALTITUDE_RELATIVE_TO_GROUND, heading, tilt, range);
    }
    catch (ex)
    {
        if (range == 0)
            range = altitude;
        la.set(lat, lng, geeZoomLevelToCameraAltitudeMap[altitude], ge.ALTITUDE_RELATIVE_TO_GROUND, heading, tilt, range);
    } 
    ge.getView().setAbstractView(la);
}
/**
 * Open a balloon in the plugin.
 * @param {Object}
 *          marker the marker that is attached to the balloon
 *          (ignored for Earth Plugin).
 * @param {Object}
 *          balloon the balloon object (this is all we need for Earth Plugin).
 * @param {string}
 *          title the title of the balloon contents.
 *          (ignored for Earth Plugin).
 * @param {string}
 *          innerText the inner text of the balloon text.
 *          (ignored for Earth Plugin).
 */
function geeOpenBalloon(marker, balloon, title, innerText) {
  ge.setBalloon(balloon);
}

/**
 * Callback for Search Results Manager after results are cleared.
 * We simply clear any active balloon.
 */
function geeClearSearchResults() {
  ge.setBalloon(null);
}
