/*********************************
JS specific to the google map.
*********************************/
// ALL the global variable to keep track.
var MARKER; // use to keep track of the current marker
var RESULTS;

// the call to the getNext method is generated in the html itself.
// Get the result with the given index
// Open the window on the current marker.
function getNext(i){
//  MARKER.openInfoWindowHtml(RESULTS[i]);
  MARKER.openInfoWindowHtml(RESULTS);
}

// Call after clicking for the first time on the marker.
function showWindow(results){
    // Keep track of the datas and trigger the click on the marker.
    RESULTS = results;
    getNext(0);
}

// function to manage the error.
function showWindowError(){
    alert('error getting your infos.');
}


// build a map ready to be use to add a new entry.
function buildMap(isProd, latitude,longitude, title){
    addMap(isProd, latitude,longitude, title);
}

function addMapEvent(){
    GEvent.addListener(MAP, 'click', function(overlay, point) {
        if (overlay){
            // didnot click on the map do nothing
        }
        else {
            if (!MARKER){
            	var icon = new GIcon();
            	icon.image = "/default/images/icon_map_past_location"
                icon.shadowSize = new GSize(28, 19);
                icon.iconAnchor = new GPoint(6, 20);
                icon.infoWindowAnchor = new GPoint(1, 1);
                MARKER = new GMarker(point, {icon:icon, title:'', draggable: true, dragCrossMove: true});
                // init the marker
                GEvent.addListener(MARKER, 'dragend', function() {
                   MARKER = this;
                   var point = MARKER.getLatLng()
                   getLocationStr(point);
                })
                MAP.addOverlay(MARKER);
                getLocationStr(point);
            }
            else {
                MARKER.setPoint(point);
                getLocationStr(point);
            } 
        }
        })
}


function addMap(isProd, latitude,longitude, title){
    if (isProd){
    	  google.load("maps","v=2.55", {"other_params":"client=gme-ekit"})
    }
    else{
        google.load("maps","v=2.55")
    }
    function initialize() {
                     MAP = new google.maps.Map2(document.getElementById("map"));
                     // with zoom based on the country... at this stage always 5
                     var coor = new GLatLng(37.4419, -122.1419);
                     MAP.setCenter(coor,5)
                     MAP.setMapType(G_NORMAL_MAP);
                     MAP.addControl(new GSmallMapControl());
                     addMapEvent();
                     
                     // add the zoom handling.
                     GEvent.addListener(MAP, 'zoomend', function(old_zoom, current_zoom){
                     process_zoom(current_zoom);
                     });
                     
                     if (latitude){
                         addMarker(latitude,longitude, title);
                     }
                }
                
                // yep when ready init it.
                google.setOnLoadCallback(initialize);
}

function addEditMap(){
    google.load("maps","v=2.55")
    function initialize() {
                     MAP = new google.maps.Map2(document.getElementById("map"));
                     // with zoom based on the country... at this stage always 5
                     var coor = new GLatLng(37.4419, -122.1419);
                     MAP.setCenter(coor,5)
                     MAP.setMapType(G_NORMAL_MAP);
                     MAP.addControl(new GSmallMapControl());
                     addMapEvent();
                     
                     // add the zoom handling.
                     GEvent.addListener(MAP, 'zoomend', function(old_zoom, current_zoom){
                     process_zoom(current_zoom);
                     });
                     do_map();

                }  
                // yep when ready init it.
                google.setOnLoadCallback(initialize);
               
}
/**
 * @name MarkerManager
 * @version 1.1
 * @copyright (c) 2007 Google Inc.
 * @author Doug Ricket, others
 *
 * @fileoverview Marker manager is an interface between the map and the user,
 * designed to manage adding and removing many points when the viewport changes.
 * <br /><br />
 * <b>How it Works</b>:<br/> 
 * The MarkerManager places its markers onto a grid, similar to the map tiles.
 * When the user moves the viewport, it computes which grid cells have
 * entered or left the viewport, and shows or hides all the markers in those
 * cells.
 * (If the users scrolls the viewport beyond the markers that are loaded,
 * no markers will be visible until the <code>EVENT_moveend</code> 
 * triggers an update.)
 * In practical consequences, this allows 10,000 markers to be distributed over
 * a large area, and as long as only 100-200 are visible in any given viewport,
 * the user will see good performance corresponding to the 100 visible markers,
 * rather than poor performance corresponding to the total 10,000 markers.
 * Note that some code is optimized for speed over space,
 * with the goal of accommodating thousands of markers.
 */

/*
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License. 
 */

/**
 * @name MarkerManagerOptions
 * @class This class represents optional arguments to the {@link MarkerManager}
 *     constructor.
 * @property {Number} [maxZoom] Sets the maximum zoom level monitored by a
 *     marker manager. If not given, the manager assumes the maximum map zoom
 *     level. This value is also used when markers are added to the manager
 *     without the optional {@link maxZoom} parameter.
 * @property {Number} [borderPadding] Specifies, in pixels, the extra padding
 *     outside the map's current viewport monitored by a manager. Markers that
 *     fall within this padding are added to the map, even if they are not fully
 *     visible.
 * @property {Boolean} [trackMarkers=false] Indicates whether or not a marker
 *     manager should track markers' movements. If you wish to move managed
 *     markers using the {@link setPoint}/{@link setLatLng} methods, 
 *     this option should be set to {@link true}.
 */

/**
 * Creates a new MarkerManager that will show/hide markers on a map.
 *
 * @constructor
 * @param {Map} map The map to manage.
 * @param {Object} opt_opts A container for optional arguments:
 *   {Number} maxZoom The maximum zoom level for which to create tiles.
 *   {Number} borderPadding The width in pixels beyond the map border,
 *                   where markers should be display.
 *   {Boolean} trackMarkers Whether or not this manager should track marker
 *                   movements.
 */
function MarkerManager(map, opt_opts) {
  var me = this;
  me.map_ = map;
  me.mapZoom_ = map.getZoom();
  me.projection_ = map.getCurrentMapType().getProjection();

  opt_opts = opt_opts || {};
  me.tileSize_ = MarkerManager.DEFAULT_TILE_SIZE_;

  var mapTypes = map.getMapTypes();
  var mapMaxZoom = mapTypes[0].getMaximumResolution();
  for (var i = 0; i < mapTypes.length; i++) {
    var mapTypeMaxZoom = mapTypes[i].getMaximumResolution();
    if (mapTypeMaxZoom > mapMaxZoom) {
      mapMaxZoom = mapTypeMaxZoom;
    }
  }
  me.maxZoom_  = opt_opts.maxZoom || mapMaxZoom;

  me.trackMarkers_ = opt_opts.trackMarkers;
  me.show_ = opt_opts.show || true;

  var padding;
  if (typeof opt_opts.borderPadding === "number") {
    padding = opt_opts.borderPadding;
  } else {
    padding = MarkerManager.DEFAULT_BORDER_PADDING_;
  }
  // The padding in pixels beyond the viewport, where we will pre-load markers.
  me.swPadding_ = new GSize(-padding, padding);
  me.nePadding_ = new GSize(padding, -padding);
  me.borderPadding_ = padding;

  me.gridWidth_ = [];

  me.grid_ = [];
  me.grid_[me.maxZoom_] = [];
  me.numMarkers_ = [];
  me.numMarkers_[me.maxZoom_] = 0;

  GEvent.bind(map, "moveend", me, me.onMapMoveEnd_);

  // NOTE: These two closures provide easy access to the map.
  // They are used as callbacks, not as methods.
  me.removeOverlay_ = function (marker) {
    map.removeOverlay(marker);
    me.shownMarkers_--;
  };
  me.addOverlay_ = function (marker) {
    if (me.show_) {
	  map.addOverlay(marker);
      me.shownMarkers_++;
    }
  };

  me.resetManager_();
  me.shownMarkers_ = 0;

  me.shownBounds_ = me.getMapGridBounds_();
}

// Static constants:
MarkerManager.DEFAULT_TILE_SIZE_ = 1024;
MarkerManager.DEFAULT_BORDER_PADDING_ = 100;
MarkerManager.MERCATOR_ZOOM_LEVEL_ZERO_RANGE = 256;


/**
 * Initializes MarkerManager arrays for all zoom levels
 * Called by constructor and by clearAllMarkers
 */
MarkerManager.prototype.resetManager_ = function () {
  var me = this;
  var mapWidth = MarkerManager.MERCATOR_ZOOM_LEVEL_ZERO_RANGE;
  for (var zoom = 0; zoom <= me.maxZoom_; ++zoom) {
    me.grid_[zoom] = [];
    me.numMarkers_[zoom] = 0;
    me.gridWidth_[zoom] = Math.ceil(mapWidth / me.tileSize_);
    mapWidth <<= 1;
  }
};

/**
 * Removes all markers in the manager, and
 * removes any visible markers from the map.
 */
MarkerManager.prototype.clearMarkers = function () {
  var me = this;
  me.processAll_(me.shownBounds_, me.removeOverlay_);
  me.resetManager_();
};


/**
 * Gets the tile coordinate for a given latlng point.
 *
 * @param {LatLng} latlng The geographical point.
 * @param {Number} zoom The zoom level.
 * @param {GSize} padding The padding used to shift the pixel coordinate.
 *               Used for expanding a bounds to include an extra padding
 *               of pixels surrounding the bounds.
 * @return {GPoint} The point in tile coordinates.
 *
 */
MarkerManager.prototype.getTilePoint_ = function (latlng, zoom, padding) {
  var pixelPoint = this.projection_.fromLatLngToPixel(latlng, zoom);
  return new GPoint(
      Math.floor((pixelPoint.x + padding.width) / this.tileSize_),
      Math.floor((pixelPoint.y + padding.height) / this.tileSize_));
};


/**
 * Finds the appropriate place to add the marker to the grid.
 * Optimized for speed; does not actually add the marker to the map.
 * Designed for batch-processing thousands of markers.
 *
 * @param {Marker} marker The marker to add.
 * @param {Number} minZoom The minimum zoom for displaying the marker.
 * @param {Number} maxZoom The maximum zoom for displaying the marker.
 */
MarkerManager.prototype.addMarkerBatch_ = function (marker, minZoom, maxZoom) {
  var mPoint = marker.getPoint();
  marker.MarkerManager_minZoom = minZoom;
  // Tracking markers is expensive, so we do this only if the
  // user explicitly requested it when creating marker manager.
  if (this.trackMarkers_) {
    GEvent.bind(marker, "changed", this, this.onMarkerMoved_);
  }

  var gridPoint = this.getTilePoint_(mPoint, maxZoom, GSize.ZERO);

  for (var zoom = maxZoom; zoom >= minZoom; zoom--) {
    var cell = this.getGridCellCreate_(gridPoint.x, gridPoint.y, zoom);
    cell.push(marker);

    gridPoint.x = gridPoint.x >> 1;
    gridPoint.y = gridPoint.y >> 1;
  }
};


/**
 * Returns whether or not the given point is visible in the shown bounds. This
 * is a helper method that takes care of the corner case, when shownBounds have
 * negative minX value.
 *
 * @param {Point} point a point on a grid.
 * @return {Boolean} Whether or not the given point is visible in the currently
 * shown bounds.
 */
MarkerManager.prototype.isGridPointVisible_ = function (point) {
  var me = this;
  var vertical = me.shownBounds_.minY <= point.y &&
      point.y <= me.shownBounds_.maxY;
  var minX = me.shownBounds_.minX;
  var horizontal = minX <= point.x && point.x <= me.shownBounds_.maxX;
  if (!horizontal && minX < 0) {
    // Shifts the negative part of the rectangle. As point.x is always less
    // than grid width, only test shifted minX .. 0 part of the shown bounds.
    var width = me.gridWidth_[me.shownBounds_.z];
    horizontal = minX + width <= point.x && point.x <= width - 1;
  }
  return vertical && horizontal;
};


/**
 * Reacts to a notification from a marker that it has moved to a new location.
 * It scans the grid all all zoom levels and moves the marker from the old grid
 * location to a new grid location.
 *
 * @param {Marker} marker The marker that moved.
 * @param {LatLng} oldPoint The old position of the marker.
 * @param {LatLng} newPoint The new position of the marker.
 */
MarkerManager.prototype.onMarkerMoved_ = function (marker, oldPoint, newPoint) {
  // NOTE: We do not know the minimum or maximum zoom the marker was
  // added at, so we start at the absolute maximum. Whenever we successfully
  // remove a marker at a given zoom, we add it at the new grid coordinates.
  var me = this;
  var zoom = me.maxZoom_;
  var changed = false;
  var oldGrid = me.getTilePoint_(oldPoint, zoom, GSize.ZERO);
  var newGrid = me.getTilePoint_(newPoint, zoom, GSize.ZERO);
  while (zoom >= 0 && (oldGrid.x !== newGrid.x || oldGrid.y !== newGrid.y)) {
    var cell = me.getGridCellNoCreate_(oldGrid.x, oldGrid.y, zoom);
    if (cell) {
      if (me.removeFromArray_(cell, marker)) {
        me.getGridCellCreate_(newGrid.x, newGrid.y, zoom).push(marker);
      }
    }
    // For the current zoom we also need to update the map. Markers that no
    // longer are visible are removed from the map. Markers that moved into
    // the shown bounds are added to the map. This also lets us keep the count
    // of visible markers up to date.
    if (zoom === me.mapZoom_) {
      if (me.isGridPointVisible_(oldGrid)) {
        if (!me.isGridPointVisible_(newGrid)) {
          me.removeOverlay_(marker);
          changed = true;
        }
      } else {
        if (me.isGridPointVisible_(newGrid)) {
          me.addOverlay_(marker);
          changed = true;
        }
      }
    }
    oldGrid.x = oldGrid.x >> 1;
    oldGrid.y = oldGrid.y >> 1;
    newGrid.x = newGrid.x >> 1;
    newGrid.y = newGrid.y >> 1;
    --zoom;
  }
  if (changed) {
    me.notifyListeners_();
  }
};


/**
 * Removes marker from the manager and from the map
 * (if it's currently visible).
 * @param {GMarker} marker The marker to delete.
 */
MarkerManager.prototype.removeMarker = function (marker) {
  var me = this;
  var zoom = me.maxZoom_;
  var changed = false;
  var point = marker.getPoint();
  var grid = me.getTilePoint_(point, zoom, GSize.ZERO);
  while (zoom >= 0) {
    var cell = me.getGridCellNoCreate_(grid.x, grid.y, zoom);

    if (cell) {
      me.removeFromArray_(cell, marker);
    }
    // For the current zoom we also need to update the map. Markers that no
    // longer are visible are removed from the map. This also lets us keep the count
    // of visible markers up to date.
    if (zoom === me.mapZoom_) {
      if (me.isGridPointVisible_(grid)) {
        me.removeOverlay_(marker);
        changed = true;
      }
    }
    grid.x = grid.x >> 1;
    grid.y = grid.y >> 1;
    --zoom;
  }
  if (changed) {
    me.notifyListeners_();
  }
  me.numMarkers_[marker.MarkerManager_minZoom]--;
};


/**
 * Add many markers at once.
 * Does not actually update the map, just the internal grid.
 *
 * @param {Array of Marker} markers The markers to add.
 * @param {Number} minZoom The minimum zoom level to display the markers.
 * @param {Number} opt_maxZoom The maximum zoom level to display the markers.
 */
MarkerManager.prototype.addMarkers = function (markers, minZoom, opt_maxZoom) {
  var maxZoom = this.getOptMaxZoom_(opt_maxZoom);
  for (var i = markers.length - 1; i >= 0; i--) {
    this.addMarkerBatch_(markers[i], minZoom, maxZoom);
  }

  this.numMarkers_[minZoom] += markers.length;
};


/**
 * Returns the value of the optional maximum zoom. This method is defined so
 * that we have just one place where optional maximum zoom is calculated.
 *
 * @param {Number} opt_maxZoom The optinal maximum zoom.
 * @return The maximum zoom.
 */
MarkerManager.prototype.getOptMaxZoom_ = function (opt_maxZoom) {
  return opt_maxZoom || this.maxZoom_;
};


/**
 * Calculates the total number of markers potentially visible at a given
 * zoom level.
 *
 * @param {Number} zoom The zoom level to check.
 */
MarkerManager.prototype.getMarkerCount = function (zoom) {
  var total = 0;
  for (var z = 0; z <= zoom; z++) {
    total += this.numMarkers_[z];
  }
  return total;
};

/** 
 * Returns a marker given latitude, longitude and zoom. If the marker does not 
 * exist, the method will return a new marker. If a new marker is created, 
 * it will NOT be added to the manager. 
 * 
 * @param {Number} lat - the latitude of a marker. 
 * @param {Number} lng - the longitude of a marker. 
 * @param {Number} zoom - the zoom level 
 * @return {GMarker} marker - the marker found at lat and lng 
 */ 
MarkerManager.prototype.getMarker = function(lat, lng, zoom) { 
  var me = this; 
  var mPoint = new GLatLng(lat, lng); 
  var gridPoint = me.getTilePoint_(mPoint, zoom, GSize.ZERO); 

  var marker = new GMarker(mPoint); 
  var cellArray = me.getGridCellNoCreate_(gridPoint.x, gridPoint.y, zoom); 
  if(cellArray != undefined){ 
    for (var i = 0; i < cellArray.length; i++) 
    { 
      if(lat == cellArray[i].getLatLng().lat() && 
         lng == cellArray[i].getLatLng().lng()) 
      { 
        marker = cellArray[i]; 
      } 
    } 
  } 
  return marker; 
}; 

/**
 * Add a single marker to the map.
 *
 * @param {Marker} marker The marker to add.
 * @param {Number} minZoom The minimum zoom level to display the marker.
 * @param {Number} opt_maxZoom The maximum zoom level to display the marker.
 */
MarkerManager.prototype.addMarker = function (marker, minZoom, opt_maxZoom) {
  var me = this;
  var maxZoom = this.getOptMaxZoom_(opt_maxZoom);
  me.addMarkerBatch_(marker, minZoom, maxZoom);
  var gridPoint = me.getTilePoint_(marker.getPoint(), me.mapZoom_, GSize.ZERO);
  if (me.isGridPointVisible_(gridPoint) &&
      minZoom <= me.shownBounds_.z &&
      me.shownBounds_.z <= maxZoom) {
    me.addOverlay_(marker);
    me.notifyListeners_();
  }
  this.numMarkers_[minZoom]++;
};

/**
 * Returns true if this bounds (inclusively) contains the given point.
 * @param {Point} point  The point to test.
 * @return {Boolean} This Bounds contains the given Point.
 */

//GBounds.prototype.containsPoint = function (point) {
//  var outer = this;
//  return (outer.minX <= point.x &&
//          outer.maxX >= point.x &&
//          outer.minY <= point.y &&
//          outer.maxY >= point.y);
//};

/**
 * Get a cell in the grid, creating it first if necessary.
 *
 * Optimization candidate
 *
 * @param {Number} x The x coordinate of the cell.
 * @param {Number} y The y coordinate of the cell.
 * @param {Number} z The z coordinate of the cell.
 * @return {Array} The cell in the array.
 */
MarkerManager.prototype.getGridCellCreate_ = function (x, y, z) {
  var grid = this.grid_[z];
  if (x < 0) {
    x += this.gridWidth_[z];
  }
  var gridCol = grid[x];
  if (!gridCol) {
    gridCol = grid[x] = [];
    return (gridCol[y] = []);
  }
  var gridCell = gridCol[y];
  if (!gridCell) {
    return (gridCol[y] = []);
  }
  return gridCell;
};


/**
 * Get a cell in the grid, returning undefined if it does not exist.
 *
 * NOTE: Optimized for speed -- otherwise could combine with getGridCellCreate_.
 *
 * @param {Number} x The x coordinate of the cell.
 * @param {Number} y The y coordinate of the cell.
 * @param {Number} z The z coordinate of the cell.
 * @return {Array} The cell in the array.
 */
MarkerManager.prototype.getGridCellNoCreate_ = function (x, y, z) {
  var grid = this.grid_[z];
  if (x < 0) {
    x += this.gridWidth_[z];
  }
  var gridCol = grid[x];
  return gridCol ? gridCol[y] : undefined;
};


/**
 * Turns at geographical bounds into a grid-space bounds.
 *
 * @param {LatLngBounds} bounds The geographical bounds.
 * @param {Number} zoom The zoom level of the bounds.
 * @param {GSize} swPadding The padding in pixels to extend beyond the
 * given bounds.
 * @param {GSize} nePadding The padding in pixels to extend beyond the
 * given bounds.
 * @return {GBounds} The bounds in grid space.
 */
MarkerManager.prototype.getGridBounds_ = function (bounds, zoom, swPadding, nePadding) {
  zoom = Math.min(zoom, this.maxZoom_);

  var bl = bounds.getSouthWest();
  var tr = bounds.getNorthEast();
  var sw = this.getTilePoint_(bl, zoom, swPadding);
  var ne = this.getTilePoint_(tr, zoom, nePadding);
  var gw = this.gridWidth_[zoom];

  // Crossing the prime meridian requires correction of bounds.
  if (tr.lng() < bl.lng() || ne.x < sw.x) {
    sw.x -= gw;
  }
  if (ne.x - sw.x  + 1 >= gw) {
    // Computed grid bounds are larger than the world; truncate.
    sw.x = 0;
    ne.x = gw - 1;
  }
  var gridBounds = new GBounds([sw, ne]);
  gridBounds.z = zoom;
  return gridBounds;
};


/**
 * Gets the grid-space bounds for the current map viewport.
 *
 * @return {Bounds} The bounds in grid space.
 */
MarkerManager.prototype.getMapGridBounds_ = function () {
  var me = this;
  return me.getGridBounds_(me.map_.getBounds(), me.mapZoom_, me.swPadding_, me.nePadding_);
};


/**
 * Event listener for map:movend.
 * NOTE: Use a timeout so that the user is not blocked
 * from moving the map.
 *
 */
MarkerManager.prototype.onMapMoveEnd_ = function () {
  var me = this;
  me.objectSetTimeout_(this, this.updateMarkers_, 0);
};


/**
 * Call a function or evaluate an expression after a specified number of
 * milliseconds.
 *
 * Equivalent to the standard window.setTimeout function, but the given
 * function executes as a method of this instance. So the function passed to
 * objectSetTimeout can contain references to this.
 *    objectSetTimeout(this, function () { alert(this.x) }, 1000);
 *
 * @param {Object} object  The target object.
 * @param {Function} command  The command to run.
 * @param {Number} milliseconds  The delay.
 * @return {Boolean}  Success.
 */
MarkerManager.prototype.objectSetTimeout_ = function (object, command, milliseconds) {
  return window.setTimeout(function () {
    command.call(object);
  }, milliseconds);
};


/**
 * Is this layer visible?
 *
 * Returns visibility setting
 *
 * @return {Boolean} Visible
 */
MarkerManager.prototype.visible = function () {
  return this.show_ ? true : false;
};


/**
 * Returns true if the manager is hidden.
 * Otherwise returns false.
 * @return {Boolean} Hidden
 */
MarkerManager.prototype.isHidden = function () {
  return !this.show_;
};


/**
 * Shows the manager if it's currently hidden.
 */
MarkerManager.prototype.show = function () {
  this.show_ = true;
  this.refresh();
};


/**
 * Hides the manager if it's currently visible
 */
MarkerManager.prototype.hide = function () {
  this.show_ = false;
  this.refresh();
};


/**
 * Toggles the visibility of the manager.
 */
MarkerManager.prototype.toggle = function () {
  this.show_ = !this.show_;
  this.refresh();
};


/**
 * Refresh forces the marker-manager into a good state.
 * <ol>
 *   <li>If never before initialized, shows all the markers.</li>
 *   <li>If previously initialized, removes and re-adds all markers.</li>
 * </ol>
 */
MarkerManager.prototype.refresh = function () {
  var me = this;
  if (me.shownMarkers_ > 0) {
    me.processAll_(me.shownBounds_, me.removeOverlay_);
  }
  // An extra check on me.show_ to increase performance (no need to processAll_)
  if (me.show_) {
    me.processAll_(me.shownBounds_, me.addOverlay_);
  }
  me.notifyListeners_();
};


/**
 * After the viewport may have changed, add or remove markers as needed.
 */
MarkerManager.prototype.updateMarkers_ = function () {
  var me = this;
  me.mapZoom_ = this.map_.getZoom();
  var newBounds = me.getMapGridBounds_();

  // If the move does not include new grid sections,
  // we have no work to do:
  if (newBounds.equals(me.shownBounds_) && newBounds.z === me.shownBounds_.z) {
    return;
  }

  if (newBounds.z !== me.shownBounds_.z) {
    me.processAll_(me.shownBounds_, me.removeOverlay_);
    if (me.show_) { // performance
      me.processAll_(newBounds, me.addOverlay_);
    }
  } else {
    // Remove markers:
    me.rectangleDiff_(me.shownBounds_, newBounds, me.removeCellMarkers_);

    // Add markers:
    if (me.show_) { // performance
      me.rectangleDiff_(newBounds, me.shownBounds_, me.addCellMarkers_);
    }
  }
  me.shownBounds_ = newBounds;

  me.notifyListeners_();
};


/**
 * Notify listeners when the state of what is displayed changes.
 */
MarkerManager.prototype.notifyListeners_ = function () {
  GEvent.trigger(this, "changed", this.shownBounds_, this.shownMarkers_);
};


/**
 * Process all markers in the bounds provided, using a callback.
 *
 * @param {Bounds} bounds The bounds in grid space.
 * @param {Function} callback The function to call for each marker.
 */
MarkerManager.prototype.processAll_ = function (bounds, callback) {
  for (var x = bounds.minX; x <= bounds.maxX; x++) {
    for (var y = bounds.minY; y <= bounds.maxY; y++) {
      this.processCellMarkers_(x, y,  bounds.z, callback);
    }
  }
};


/**
 * Process all markers in the grid cell, using a callback.
 *
 * @param {Number} x The x coordinate of the cell.
 * @param {Number} y The y coordinate of the cell.
 * @param {Number} z The z coordinate of the cell.
 * @param {Function} callback The function to call for each marker.
 */
MarkerManager.prototype.processCellMarkers_ = function (x, y, z, callback) {
  var cell = this.getGridCellNoCreate_(x, y, z);
  if (cell) {
    for (var i = cell.length - 1; i >= 0; i--) {
      callback(cell[i]);
    }
  }
};


/**
 * Remove all markers in a grid cell.
 *
 * @param {Number} x The x coordinate of the cell.
 * @param {Number} y The y coordinate of the cell.
 * @param {Number} z The z coordinate of the cell.
 */
MarkerManager.prototype.removeCellMarkers_ = function (x, y, z) {
  this.processCellMarkers_(x, y, z, this.removeOverlay_);
};


/**
 * Add all markers in a grid cell.
 *
 * @param {Number} x The x coordinate of the cell.
 * @param {Number} y The y coordinate of the cell.
 * @param {Number} z The z coordinate of the cell.
 */
MarkerManager.prototype.addCellMarkers_ = function (x, y, z) {
  this.processCellMarkers_(x, y, z, this.addOverlay_);
};


/**
 * Use the rectangleDiffCoords_ function to process all grid cells
 * that are in bounds1 but not bounds2, using a callback, and using
 * the current MarkerManager object as the instance.
 *
 * Pass the z parameter to the callback in addition to x and y.
 *
 * @param {Bounds} bounds1 The bounds of all points we may process.
 * @param {Bounds} bounds2 The bounds of points to exclude.
 * @param {Function} callback The callback function to call
 *                   for each grid coordinate (x, y, z).
 */
MarkerManager.prototype.rectangleDiff_ = function (bounds1, bounds2, callback) {
  var me = this;
  me.rectangleDiffCoords_(bounds1, bounds2, function (x, y) {
    callback.apply(me, [x, y, bounds1.z]);
  });
};


/**
 * Calls the function for all points in bounds1, not in bounds2
 *
 * @param {Bounds} bounds1 The bounds of all points we may process.
 * @param {Bounds} bounds2 The bounds of points to exclude.
 * @param {Function} callback The callback function to call
 *                   for each grid coordinate.
 */
MarkerManager.prototype.rectangleDiffCoords_ = function (bounds1, bounds2, callback) {
  var minX1 = bounds1.minX;
  var minY1 = bounds1.minY;
  var maxX1 = bounds1.maxX;
  var maxY1 = bounds1.maxY;
  var minX2 = bounds2.minX;
  var minY2 = bounds2.minY;
  var maxX2 = bounds2.maxX;
  var maxY2 = bounds2.maxY;

  var x, y;
  for (x = minX1; x <= maxX1; x++) {  // All x in R1
    // All above:
    for (y = minY1; y <= maxY1 && y < minY2; y++) {  // y in R1 above R2
      callback(x, y);
    }
    // All below:
    for (y = Math.max(maxY2 + 1, minY1);  // y in R1 below R2
         y <= maxY1; y++) {
      callback(x, y);
    }
  }

  for (y = Math.max(minY1, minY2);
       y <= Math.min(maxY1, maxY2); y++) {  // All y in R2 and in R1
    // Strictly left:
    for (x = Math.min(maxX1 + 1, minX2) - 1;
         x >= minX1; x--) {  // x in R1 left of R2
      callback(x, y);
    }
    // Strictly right:
    for (x = Math.max(minX1, maxX2 + 1);  // x in R1 right of R2
         x <= maxX1; x++) {
      callback(x, y);
    }
  }
};


/**
 * Removes value from array. O(N).
 *
 * @param {Array} array  The array to modify.
 * @param {any} value  The value to remove.
 * @param {Boolean} opt_notype  Flag to disable type checking in equality.
 * @return {Number}  The number of instances of value that were removed.
 */
MarkerManager.prototype.removeFromArray_ = function (array, value, opt_notype) {
  var shift = 0;
  for (var i = 0; i < array.length; ++i) {
    if (array[i] === value || (opt_notype && array[i] === value)) {
      array.splice(i--, 1);
      shift++;
    }
  }
  return shift;
};

function draw_poly(){
    // draw all the poly on the map.

    for ( var i =0; i < latslngs.length-1; i++){
        var polyline = new GPolyline([
            latslngs[i],
     	    latslngs[i+1]
           ], "#000000", 2, 1);
	MAP.addOverlay(polyline);
        polys.push(polyline);
    }
}

function hide_poly(){
    for ( var i =0; i < polys.length; i++){
         MAP.removeOverlay(polys[i]) ;
    }
}

function check_poly(){
    // hide all the poly on the map.
    if ($("#lines:checked").length){
        draw_poly();
    }
    else {
        hide_poly();
    }
}

var boundaries =  new Array ();
boundaries[0] = ['samoa', -172, -14, -171, -13]; boundaries[1] = ['japan', 127, 26, 145, 45]; boundaries[2] = ['kosovo', 19, 41, 21, 43]; boundaries[3] = ['azerbaijan', 44, 38, 50, 41]; boundaries[4] = ['russian fed.', 26, 41, 180, 83]; boundaries[5] = ['djibouti', 41, 10, 43, 12]; boundaries[6] = ['french guiana', -54, 2, -51, 5]; boundaries[7] = ['malta', 14, 35, 14, 36]; boundaries[8] = ['guinea-bissau', -16, 10, -13, 12]; boundaries[9] = ['hungary', 16, 45, 22, 48]; boundaries[10] = ['taiwan', 120, 21, 121, 25]; boundaries[11] = ['cyprus', 32, 34, 34, 35]; boundaries[12] = ['barbados', -59, 13, -59, 13]; boundaries[13] = ['bhutan', 88, 26, 92, 28]; boundaries[14] = ['french southern and antarctic lands', 68, -49, 70, -48]; boundaries[15] = ['lithuania', 20, 53, 26, 56]; boundaries[16] = ['mongolia', 87, 41, 119, 52]; boundaries[17] = ['andorra', 1, 42, 1, 42]; boundaries[18] = ['tunisia', 7, 30, 11, 37]; boundaries[19] = ['rwanda', 28, -2, 30, -1]; boundaries[20] = ['aruba', -70, 12, -69, 12]; boundaries[21] = ['puerto rico', -67, 17, -65, 18]; boundaries[22] = ['argentina', -73, -55, -53, -21]; boundaries[23] = ['norway', -9, 57, 33, 80]; boundaries[24] = ['sierra leone', -13, 6, -10, 9]; boundaries[25] = ['ghana', -3, 4, 1, 11]; boundaries[26] = ['falkland islands', -61, -52, -57, -51]; boundaries[27] = ['serbia', 18, 42, 23, 46]; boundaries[28] = ['australia', 112, -43, 153, -10]; boundaries[29] = ['saint helena', -5, -16, -5, -15]; boundaries[30] = ['cuba', -84, 19, -74, 23]; boundaries[31] = ['south georgia and the south sandwich isl', -38, -54, -35, -54]; boundaries[32] = ['zambia', 21, -18, 33, -8]; boundaries[33] = ['french polynesia', -149, -17, -149, -17]; boundaries[34] = ['guatemala', -92, 13, -88, 17]; boundaries[35] = ['isle of man', -4, 54, -4, 54]; boundaries[36] = ['belgium', 2, 49, 6, 51]; boundaries[37] = ['haiti', -74, 18, -71, 19]; boundaries[38] = ['macau', 113, 22, 113, 22]; boundaries[39] = ['kazakhstan', 46, 40, 87, 55]; boundaries[40] = ['burkina faso', -5, 9, 2, 15]; boundaries[41] = ['liberia', -11, 4, -7, 8]; boundaries[42] = ['kyrgyzstan', 69, 39, 80, 43]; boundaries[43] = ['netherlands', 3, 50, 7, 53]; boundaries[44] = ['portugal', -28, 32, -6, 42]; boundaries[45] = ['denmark', 8, 54, 12, 57]; boundaries[46] = ['philippines', 117, 5, 126, 18]; boundaries[47] = ['senegal', -17, 12, -11, 16]; boundaries[48] = ['moldova', 26, 45, 30, 48]; boundaries[49] = ['congo', 12, -13, 31, 5]; boundaries[50] = ['croatia', 13, 42, 19, 46]; boundaries[51] = ['sri lanka', 79, 5, 81, 9]; boundaries[52] = ['bulgaria', 22, 41, 28, 44]; boundaries[53] = ['jamaica', -78, 17, -76, 18]; boundaries[54] = ['albania', 19, 39, 21, 42]; boundaries[55] = ['angola', 11, -18, 24, -4]; boundaries[56] = ['lebanon', 35, 33, 36, 34]; boundaries[57] = ['malaysia', 99, 0, 119, 7]; boundaries[58] = ['mozambique', 30, -26, 40, -10]; boundaries[59] = ['thailand', 97, 5, 105, 20]; boundaries[60] = ['greece', 19, 34, 28, 41]; boundaries[61] = ['nicaragua', -87, 10, -83, 15]; boundaries[62] = ['niger', 0, 11, 15, 23]; boundaries[63] = ['canada', -141, 41, -52, 83]; boundaries[64] = ['afghanistan', 60, 29, 74, 38]; boundaries[65] = ['qatar', 50, 24, 51, 26]; boundaries[66] = ['turkmenistan', 52, 35, 66, 42]; boundaries[67] = ['equatorial guinea', 9, 1, 11, 2]; boundaries[68] = ['sudan', 21, 3, 38, 23]; boundaries[69] = ['guinea', -15, 3, 8, 12]; boundaries[70] = ['panama', -83, 7, -77, 9]; boundaries[71] = ['nepal', 80, 26, 88, 30]; boundaries[72] = ['central african republic', 14, 2, 27, 11]; boundaries[73] = ['luxembourg', 5, 49, 6, 50]; boundaries[74] = ['solomon islands', 154, -11, 162, -5]; boundaries[75] = ['latvia', 20, 55, 28, 58]; boundaries[76] = ['somalia', 40, -1, 54, 12]; boundaries[77] = ['tuvalu', 178, -8, 179, -7]; boundaries[78] = ['netherlands antilles', -70, 12, -68, 12]; boundaries[79] = ['namibia', 11, -28, 25, -16]; boundaries[80] = ['venezuela', -73, 0, -59, 12]; boundaries[81] = ['brunei', 114, 4, 115, 5]; boundaries[82] = ['korea', 126, 33, 129, 38]; boundaries[83] = ['iran', 44, 25, 63, 39]; boundaries[84] = ['united arab emirates', 50, 22, 56, 26]; boundaries[85] = ['mali', -12, 10, 4, 25]; boundaries[86] = ['saudi arabia', 34, 15, 56, 32]; boundaries[87] = ['switzerland', 5, 45, 10, 47]; boundaries[88] = ['paraguay', -62, -27, -54, -19]; boundaries[89] = ['china', 73, 18, 134, 53]; boundaries[90] = ['armenia', 43, 38, 46, 41]; boundaries[91] = ['kiribati', -157, 1, -157, 2]; boundaries[92] = ['belize', -89, 15, -88, 18]; boundaries[93] = ['ukraine', 22, 44, 40, 52]; boundaries[94] = ['yemen', 42, 12, 53, 18]; boundaries[95] = ['northern mariana islands', 144, 13, 144, 13]; boundaries[96] = ['libya', 9, 19, 25, 33]; boundaries[97] = ['trinidad and tobago', -61, 10, -60, 10]; boundaries[98] = ['gambia', -16, 13, -13, 13]; boundaries[99] = ['finland', 19, 59, 31, 70]; boundaries[100] = ['macedonia', 20, 40, 23, 42]; boundaries[101] = ['mauritius', 57, -20, 57, -20]; boundaries[102] = ['antigua and barbuda', -61, 16, -61, 17]; boundaries[103] = ['estonia', 21, 57, 28, 59]; boundaries[104] = ['syria', 35, 32, 42, 37]; boundaries[105] = ['dominican republic', -71, 17, -68, 19]; boundaries[106] = ['pakistan', 60, 23, 77, 37]; boundaries[107] = ['romania', 20, 43, 29, 48]; boundaries[108] = ['seychelles', 55, -4, 55, -4]; boundaries[109] = ['czech republic', 12, 48, 18, 51]; boundaries[110] = ['myanmar', 92, 9, 101, 28]; boundaries[111] = ['egypt', 24, 21, 35, 31]; boundaries[112] = ['papua new guinea', 140, -11, 153, -1]; boundaries[113] = ['united states', -178, 18, -48, 71]; boundaries[114] = ['austria', 9, 46, 17, 49]; boundaries[115] = ['greenland', -73, 59, -12, 83]; boundaries[116] = ['colombia', -79, -4, -66, 12]; boundaries[117] = ['st vincent and the grenadines', -61, 12, -61, 13]; boundaries[118] = ['honduras', -89, 12, -83, 16]; boundaries[119] = ['new zealand', 165, -50, 178, -33]; boundaries[120] = ['fiji', 177, -19, 179, -16]; boundaries[121] = ['comoros', 43, -12, 44, -11]; boundaries[122] = ['turkey', 26, 35, 44, 42]; boundaries[123] = ['united kingdom', -8, 49, 1, 60]; boundaries[124] = ['madagascar', 43, -25, 50, -11]; boundaries[125] = ['iraq', 38, 29, 48, 37]; boundaries[126] = ['bangladesh', 88, 20, 92, 26]; boundaries[127] = ['mauritania', -17, 14, -4, 27]; boundaries[128] = ['bosnia - herzegovina', 15, 42, 19, 45]; boundaries[129] = ['uruguay', -58, -34, -53, -30]; boundaries[130] = ['france', -4, 41, 9, 51]; boundaries[131] = ['bahamas', -78, 22, -73, 26]; boundaries[132] = ['slovakia', 16, 47, 22, 49]; boundaries[133] = ['ireland', -10, 51, -5, 55]; boundaries[134] = ['laos', 100, 13, 107, 22]; boundaries[135] = ['nigeria', 2, 4, 14, 13]; boundaries[136] = ['bolivia', -69, -22, -57, -9]; boundaries[137] = ['malawi', 32, -17, 35, -9]; boundaries[138] = ['ecuador', -91, -5, -75, 1]; boundaries[139] = ['israel', 34, 29, 35, 33]; boundaries[140] = ['peru', -81, -18, -68, 0]; boundaries[141] = ['algeria', -8, 18, 11, 37]; boundaries[142] = ['san marino', 12, 43, 12, 43]; boundaries[143] = ['gaza strip', 34, 31, 34, 31]; boundaries[144] = ['montenegro', 18, 41, 20, 43]; boundaries[145] = ['tajikistan', 67, 36, 75, 41]; boundaries[146] = ['togo', 0, 6, 1, 11]; boundaries[147] = ['jordan', 34, 29, 39, 33]; boundaries[148] = ['chile', -75, -55, -67, -17]; boundaries[149] = ['martinique', -61, 14, -60, 14]; boundaries[150] = ['oman', 51, 16, 59, 25]; boundaries[151] = ['turks and caicos islands', -73, 20, -73, 21]; boundaries[152] = ['spain', -17, 27, 4, 43]; boundaries[153] = ['sao tome and principe', 6, 0, 7, 1]; boundaries[154] = ['georgia', 40, 41, 46, 43]; boundaries[155] = ['viet nam', 102, 8, 109, 23]; boundaries[156] = ['american samoa', -170, -14, -170, -14]; boundaries[157] = ['morocco', -13, 27, -1, 35]; boundaries[158] = ['sweden', 11, 55, 24, 69]; boundaries[159] = ['gabon', 8, -3, 14, 2]; boundaries[160] = ['guyana', -61, 1, -56, 8]; boundaries[161] = ['grenada', -61, 11, -61, 12]; boundaries[162] = ['guadeloupe', -61, 15, -61, 16]; boundaries[163] = ['hong kong', 113, 22, 114, 22]; boundaries[164] = ['tanzania', 29, -11, 40, 0]; boundaries[165] = ['cameroon united republic', 8, 1, 16, 13]; boundaries[166] = ['bahrain', 50, 25, 50, 26]; boundaries[167] = ['chad', 13, 7, 23, 23]; boundaries[168] = ['mexico', -117, 14, -86, 32]; boundaries[169] = ['reunion', 55, -21, 55, -20]; boundaries[170] = ['india', 68, 6, 97, 35]; boundaries[171] = ['new caledonia', 163, -22, 168, -20]; boundaries[172] = ['st lucia', -61, 13, -60, 14]; boundaries[173] = ['lesotho', 27, -30, 29, -28]; boundaries[174] = ['heard island and mcdonald islands', 73, -53, 73, -52]; boundaries[175] = ['uganda', 29, -1, 35, 4]; boundaries[176] = ['burundi', 28, -4, 30, -2]; boundaries[177] = ['kenya', 33, -4, 41, 4]; boundaries[178] = ['botswana', 19, -26, 29, -17]; boundaries[179] = ['italy', 6, 36, 18, 47]; boundaries[180] = ['western sahara', -17, 20, -8, 27]; boundaries[181] = ['south africa', 16, -34, 32, -22]; boundaries[182] = ['st kitts nevis', -62, 17, -62, 17]; boundaries[183] = ['liechtenstein', 9, 47, 9, 47]; boundaries[184] = ['cambodia', 102, 10, 107, 14]; boundaries[185] = ['ivory coast', -8, 4, -2, 10]; boundaries[186] = ['ethiopia', 32, 3, 47, 14]; boundaries[187] = ['swaziland', 30, -27, 32, -25]; boundaries[188] = ['bermuda', -64, 32, -64, 32]; boundaries[189] = ['vanuatu', 165, -19, 169, -10]; boundaries[190] = ['benin', 0, 6, 3, 12]; boundaries[191] = ['brazil', -74, -33, -34, 5]; boundaries[192] = ['singapore', 103, 1, 103, 1]; boundaries[193] = ['faroe islands', -7, 61, -6, 62]; boundaries[194] = ['iceland', -24, 63, -13, 66]; boundaries[195] = ['costa rica', -85, 8, -82, 11]; boundaries[196] = ['british virgin island', -64, 18, -63, 18]; boundaries[197] = ['slovenia', 13, 45, 16, 46]; boundaries[198] = ['germany', 5, 47, 15, 54]; boundaries[199] = ['dominica', -61, 15, -61, 15]; boundaries[200] = ['suriname', -58, 1, -53, 5]; boundaries[201] = ['eritrea', 36, 12, 43, 18]; boundaries[202] = ['tonga', -175, -21, -173, -18]; boundaries[203] = ['maldives', 72, 0, 73, 7]; boundaries[204] = ['uzbekistan', 55, 37, 73, 45]; boundaries[205] = ['el salvador', -90, 13, -87, 14]; boundaries[206] = ['poland', 14, 49, 24, 54]; boundaries[207] = ['indonesia', 95, -10, 141, 5]; boundaries[208] = ['cape verde', -25, 14, -22, 17]; boundaries[209] = ['belarus', 19, 51, 32, 56]; boundaries[210] = ['zimbabwe', 25, -22, 33, -15]; boundaries[211] = ['kuwait', 46, 28, 48, 30]; 