/* infobox.js */

/**
 * @name InfoBox
 * @version 1.0.3 [August 21, 2010]
 * @author Gary Little (inspired by proof-of-concept code from Pamela Fox of Google)
 * @copyright Copyright 2010 Gary Little [gary at luxcentral.com]
 * @fileoverview InfoBox extends the Google Maps JavaScript API V3 <tt>OverlayView</tt> class.
 *  <p>
 *  An InfoBox behaves like a <tt>google.maps.InfoWindow</tt>, but it supports several
 *  additional properties for advanced styling. An InfoBox can also be used as a map label.
 *  <p>
 *  An InfoBox also fires the same events as a <tt>google.maps.InfoWindow</tt>.
 *  <p>
 *  Browsers tested:
 *  <p>
 *  Mac -- Safari (4.0.4), Firefox (3.6), Opera (10.10), Chrome (4.0.249.43), OmniWeb (5.10.1)
 *  <br>
 *  Win -- Safari, Firefox, Opera, Chrome (3.0.195.38), Internet Explorer (8.0.6001.18702)
 *  <br>
 *  iPod Touch/iPhone -- Safari (3.1.2)
 */

/*!
 *
 * 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.
 */

/*jslint browser:true */
/*global google */

/**
 * @name InfoBoxOptions
 * @class This class represents the optional parameter passed to the {@link InfoBox} constructor.
 * @property {string|Node} content The content of the InfoBox (plain text or an HTML DOM node).
 * @property {boolean} disableAutoPan Disable auto-pan on <tt>open</tt> (default is <tt>false</tt>).
 * @property {number} maxWidth The maximum width (in pixels) of the InfoBox. Set to 0 if no maximum.
 * @property {Size} pixelOffset The offset (in pixels) from the top left corner of the InfoBox
 *  to the map pixel corresponding to <tt>position</tt>.
 * @property {LatLng} position The geographic location at which to display the InfoBox.
 * @property {number} zIndex The CSS z-index style value for the InfoBox.
 *  Note: This value overrides a zIndex setting specified in the <tt>boxStyle</tt> property.
 * @property {Object} boxStyle An object literal with CSS style settings for the InfoBox container.
 *  Note: Border widths must be specified in px units because of an MSIE limitation.
 * @property {string} closeBoxMargin The CSS margin style value for the close box.
 *  The default is "2px" (a 2-pixel margin on all sides).
 * @property {string} closeBoxURL The URL of the image representing the close box.
 *  Note: The default is the URL for Google's standard close box.
 *  Set this property to "" if no close box is required.
 * @property {Size} infoBoxClearance Minimum offset (in pixels) from the InfoBox to the
 *  map edge after an auto-pan.
 * @property {boolean} isHidden Hide the InfoBox on <tt>open</tt> (default is <tt>false</tt>).
 * @property {string} pane The pane where the InfoBox is to appear (default is "floatPane").
 *  Set the pane to "mapPane" if the InfoBox is being used as a map label.
 *  Valid pane names are the property names for the <tt>google.maps.MapPanes</tt> object.
 * @property {boolean} enableEventPropagation Propagate mousedown, click, dblclick,
 *  and contextmenu events in the InfoBox (default is <tt>false</tt> to mimic the behavior
 *  of a <tt>google.maps.InfoWindow</tt>). Set this property to <tt>true</tt> if the InfoBox
 *  is being used as a map label. iPhone note: This property setting has no effect. Events are
 *  always propagated for an InfoBox in the "mapPane" pane and they are <i>not</i> propagated
 *  for an InfoBox in the "floatPane" pane.
 */

/**
 * Creates an InfoBox with the options specified in {@link InfoBoxOptions}.
 *  Call <tt>InfoBox.open</tt> to add the box to the map.
 * @constructor
 * @param {InfoBoxOptions} [opt_opts]
 */
function InfoBox(opt_opts) {

  opt_opts = opt_opts || {};

  google.maps.OverlayView.apply(this, arguments);

  // Standard options (in common with google.maps.InfoWindow):
  //
  this.content_ = opt_opts.content || "";
  this.disableAutoPan_ = opt_opts.disableAutoPan || false;
  this.maxWidth_ = opt_opts.maxWidth || 0;
  this.pixelOffset_ = opt_opts.pixelOffset || new google.maps.Size(0, 0);
  this.position_ = opt_opts.position || new google.maps.LatLng(0, 0);
  this.zIndex_ = opt_opts.zIndex || null;

  // Additional options (unique to InfoBox):
  //
  this.boxStyle_ = opt_opts.boxStyle || {};
  this.closeBoxMargin_ = opt_opts.closeBoxMargin || "2px";
  this.closeBoxURL_ = opt_opts.closeBoxURL || "http://www.google.com/intl/en_us/mapfiles/close.gif";
  if (opt_opts.closeBoxURL === "") {
    this.closeBoxURL_ = "";
  }
  this.infoBoxClearance_ = opt_opts.infoBoxClearance || new google.maps.Size(1, 1);
  this.isHidden_ = opt_opts.isHidden || false;
  this.pane_ = opt_opts.pane || "floatPane";
  this.enableEventPropagation_ = opt_opts.enableEventPropagation || false;

  this.div_ = null;
  this.closeListener_ = null;
  this.eventListener1_ = null;
  this.eventListener2_ = null;
  this.eventListener3_ = null;
  this.contextListener_ = null;
  this.fixedWidthSet_ = null;
}

/* InfoBox extends OverlayView in the Google Maps API v3.
 */
InfoBox.prototype = new google.maps.OverlayView();

/**
 * Creates the DIV representing the InfoBox.
 * @private
 */
InfoBox.prototype.createInfoBoxDiv_ = function () {

  var bw;
  var me = this;

  // This handler prevents an event in the InfoBox from being passed on to the map.
  //
  var cancelHandler = function (e) {
    e.cancelBubble = true;

    if (e.stopPropagation) {

      e.stopPropagation();
    }
  };

  // This handler ignores the current event in the InfoBox and conditionally prevents
  // the event from being passed on to the map. It is used for the contextmenu event.
  //
  var ignoreHandler = function (e) {

    e.returnValue = false;

    if (e.preventDefault) {

      e.preventDefault();
    }

    if (!me.enableEventPropagation_) {

      cancelHandler(e);
    }
  };

  if (!this.div_) {

    this.div_ = document.createElement("div");

    this.setBoxStyle_();

    // Apply required styles:
    //
    this.div_.style.position = "absolute";
    this.div_.style.visibility = 'hidden';
    if (this.zIndex_ !== null) {

      this.div_.style.zIndex = this.zIndex_;
    }

    if (typeof this.content_.nodeType === "undefined") {
      this.div_.innerHTML = this.getCloseBoxImg_() + this.content_;
    } else {
      this.div_.innerHTML = this.getCloseBoxImg_();
      this.div_.appendChild(this.content_);
    }

    // Add the InfoBox DIV to the DOM
    this.getPanes()[this.pane_].appendChild(this.div_);

    this.addClickHandler_();

    if (this.div_.style.width) {

      this.fixedWidthSet_ = true;

    } else {

      if (this.maxWidth_ !== 0 && this.div_.offsetWidth > this.maxWidth_) {

        this.div_.style.width = this.maxWidth_;
        this.div_.style.overflow = "auto";
        this.fixedWidthSet_ = true;

      } else { // The following code is needed to overcome problems with MSIE

        bw = this.getBoxWidths_();

        this.div_.style.width = (this.div_.offsetWidth - bw.left - bw.right) + "px";
        this.fixedWidthSet_ = false;
      }
    }

    this.panBox_(this.disableAutoPan_);

    if (!this.enableEventPropagation_) {

      // Cancel event propagation.
      //
      this.eventListener1_ = google.maps.event.addDomListener(this.div_, "mousedown", cancelHandler);
      this.eventListener2_ = google.maps.event.addDomListener(this.div_, "click", cancelHandler);
      this.eventListener3_ = google.maps.event.addDomListener(this.div_, "dblclick", cancelHandler);
    }

    this.contextListener_ = google.maps.event.addDomListener(this.div_, "contextmenu", ignoreHandler);

    /**
     * This event is fired when the DIV containing the InfoBox's content is attached to the DOM.
     * @name InfoBox#domready
     * @event
     */
    google.maps.event.trigger(this, "domready");
  }
};

/**
 * Returns the HTML <IMG> tag for the close box.
 * @private
 */
InfoBox.prototype.getCloseBoxImg_ = function () {

  var img = "";

  if (this.closeBoxURL_ !== "") {

    img  = "<img";
    img += " src='" + this.closeBoxURL_ + "'";
    img += " align=right"; // Do this because Opera chokes on style='float: right;'
    img += " style='";
    img += " position: relative;"; // Required by MSIE
    img += " cursor: pointer;";
    img += " z-index: 100;";
    img += " margin: " + this.closeBoxMargin_ + ";";
    img += "'>";
  }

  return img;
};

/**
 * Adds the click handler to the InfoBox close box.
 * @private
 */
InfoBox.prototype.addClickHandler_ = function () {

  var closeBox;

  if (this.closeBoxURL_ !== "") {

    closeBox = this.div_.firstChild;
    this.closeListener_ = google.maps.event.addDomListener(closeBox, 'click', this.getCloseClickHandler_());

  } else {

    this.closeListener_ = null;
  }
};

/**
 * Returns the function to call when the user clicks the close box of an InfoBox.
 * @private
 */
InfoBox.prototype.getCloseClickHandler_ = function () {

  var me = this;

  return function (e) {

	// 1.0.3 fix: Always prevent propagation of a close box click to the map:
    e.cancelBubble = true;

    if (e.stopPropagation) {

      e.stopPropagation();
    }

    me.close();

    /**
     * This event is fired when the InfoBox's close box is clicked.
     * @name InfoBox#closeclick
     * @event
     */
    google.maps.event.trigger(me, "closeclick");
  };
};

/**
 * Pans the map so that the InfoBox appears entirely within the map's visible area.
 * @private
 */
InfoBox.prototype.panBox_ = function (disablePan) {

  if (!disablePan) {

    var map = this.getMap();
    var bounds = map.getBounds();

    // The degrees per pixel
    var mapDiv = map.getDiv();
    var mapWidth = mapDiv.offsetWidth;
    var mapHeight = mapDiv.offsetHeight;
    var boundsSpan = bounds.toSpan();
    var longSpan = boundsSpan.lng();
    var latSpan = boundsSpan.lat();
    var degPixelX = longSpan / mapWidth;
    var degPixelY = latSpan / mapHeight;

    // The bounds of the map
    var mapWestLng = bounds.getSouthWest().lng();
    var mapEastLng = bounds.getNorthEast().lng();
    var mapNorthLat = bounds.getNorthEast().lat();
    var mapSouthLat = bounds.getSouthWest().lat();

    // The bounds of the box
    var position = this.position_;
    var iwOffsetX = this.pixelOffset_.width;
    var iwOffsetY = this.pixelOffset_.height;
    var padX = this.infoBoxClearance_.width;
    var padY = this.infoBoxClearance_.height;
    var iwWestLng = position.lng() + (iwOffsetX - padX) * degPixelX;
    var iwEastLng = position.lng() + (iwOffsetX + this.div_.offsetWidth + padX) * degPixelX;
    var iwNorthLat = position.lat() - (iwOffsetY - padY) * degPixelY;
    var iwSouthLat = position.lat() - (iwOffsetY + this.div_.offsetHeight + padY) * degPixelY;

    // Calculate center shift
    var shiftLng =
      (iwWestLng < mapWestLng ? mapWestLng - iwWestLng : 0) +
      (iwEastLng > mapEastLng ? mapEastLng - iwEastLng : 0);
    var shiftLat =
      (iwNorthLat > mapNorthLat ? mapNorthLat - iwNorthLat : 0) +
      (iwSouthLat < mapSouthLat ? mapSouthLat - iwSouthLat : 0);

    if (!(shiftLat === 0 && shiftLng === 0)) {

      // Move the map to the new shifted center.
      //
      var c = map.getCenter();
      map.setCenter(new google.maps.LatLng(c.lat() - shiftLat, c.lng() - shiftLng));
    }
  }
};

/**
 * Sets the style of the InfoBox.
 * @private
 */
InfoBox.prototype.setBoxStyle_ = function () {

  var i;

  var boxStyle = this.boxStyle_;

  for (i in boxStyle) {

    if (boxStyle.hasOwnProperty(i)) {

      this.div_.style[i] = boxStyle[i];
    }
  }

  // Fix up opacity style for benefit of MSIE:
  //
  if (typeof this.div_.style.opacity !== "undefined") {

    this.div_.style.filter = "alpha(opacity=" + (this.div_.style.opacity * 100) + ")";
  }
};

/**
 * Get the widths of the borders of the InfoBox.
 * @private
 * @return {Object} widths object (top, bottom left, right)
 */
InfoBox.prototype.getBoxWidths_ = function () {

  var computedStyle;
  var bw = {top: 0, bottom: 0, left: 0, right: 0};
  var box = this.div_;

  if (document.defaultView && document.defaultView.getComputedStyle) {

    computedStyle = box.ownerDocument.defaultView.getComputedStyle(box, "");

    if (computedStyle) {

      // The computed styles are always in pixel units (good!)
      bw.top = parseInt(computedStyle.borderTopWidth, 10) || 0;
      bw.bottom = parseInt(computedStyle.borderBottomWidth, 10) || 0;
      bw.left = parseInt(computedStyle.borderLeftWidth, 10) || 0;
      bw.right = parseInt(computedStyle.borderRightWidth, 10) || 0;
    }

  } else if (document.documentElement.currentStyle) { // MSIE

    if (box.currentStyle) {

      // The current styles may not be in pixel units, but assume they are (bad!)
      bw.top = parseInt(box.currentStyle.borderTopWidth, 10) || 0;
      bw.bottom = parseInt(box.currentStyle.borderBottomWidth, 10) || 0;
      bw.left = parseInt(box.currentStyle.borderLeftWidth, 10) || 0;
      bw.right = parseInt(box.currentStyle.borderRightWidth, 10) || 0;
    }
  }

  return bw;
};

/**
 * Invoked when <tt>close</tt> is called. Do not call it directly.
 */
InfoBox.prototype.onRemove = function () {

  if (this.div_) {

    this.div_.parentNode.removeChild(this.div_);
    this.div_ = null;
  }
};

/**
 * Draws the InfoBox based on the current map projection and zoom level.
 */
InfoBox.prototype.draw = function () {

  this.createInfoBoxDiv_();

  var pixPosition = this.getProjection().fromLatLngToDivPixel(this.position_);

  this.div_.style.left = (pixPosition.x + this.pixelOffset_.width) + "px";
  this.div_.style.top = (pixPosition.y + this.pixelOffset_.height) + "px";

  if (this.isHidden_) {

    this.div_.style.visibility = 'hidden';

  } else {

    this.div_.style.visibility = "visible";
  }
};

/**
 * Sets the options for the InfoBox. Note that changes to the <tt>maxWidth</tt>,
 *  <tt>closeBoxMargin</tt>, <tt>closeBoxURL</tt>, and <tt>enableEventPropagation</tt>
 *  properties have no affect until the current InfoBox is <tt>close</tt>d and a new one
 *  is <tt>open</tt>ed.
 * @param {InfoBoxOptions} opt_opts
 */
InfoBox.prototype.setOptions = function (opt_opts) {

  if (typeof opt_opts.boxStyle !== "undefined") { // Must be first

    this.boxStyle_ = opt_opts.boxStyle;
    this.setBoxStyle_();
  }
  if (typeof opt_opts.content !== "undefined") {

    this.setContent(opt_opts.content);
  }
  if (typeof opt_opts.disableAutoPan !== "undefined") {

    this.disableAutoPan_ = opt_opts.disableAutoPan;
  }
  if (typeof opt_opts.maxWidth !== "undefined") {

    this.maxWidth_ = opt_opts.maxWidth;
  }
  if (typeof opt_opts.pixelOffset !== "undefined") {

    this.pixelOffset_ = opt_opts.pixelOffset;
  }
  if (typeof opt_opts.position !== "undefined") {

    this.setPosition(opt_opts.position);
  }
  if (typeof opt_opts.zIndex !== "undefined") {

    this.setZIndex(opt_opts.zIndex);
  }
  if (typeof opt_opts.closeBoxMargin !== "undefined") {

    this.closeBoxMargin_ = opt_opts.closeBoxMargin;
  }
  if (typeof opt_opts.closeBoxURL !== "undefined") {

    this.closeBoxURL_ = opt_opts.closeBoxURL;
  }
  if (typeof opt_opts.infoBoxClearance !== "undefined") {

    this.infoBoxClearance_ = opt_opts.infoBoxClearance;
  }
  if (typeof opt_opts.isHidden !== "undefined") {

    this.isHidden_ = opt_opts.isHidden;
  }

  if (typeof opt_opts.enableEventPropagation !== "undefined") {

    this.enableEventPropagation_ = opt_opts.enableEventPropagation;
  }

  if (this.div_) {

    this.draw();
  }
};

/**
 * Sets the content of the InfoBox.
 *  The content can be plain text or an HTML DOM node.
 * @param {string|Node} content
 */
InfoBox.prototype.setContent = function (content) {
  this.content_ = content;

  if (this.div_) {

    if (this.closeListener_) {

      google.maps.event.removeListener(this.closeListener_);
      this.closeListener_ = null;
    }

    // Odd code required to make things work with MSIE.
    //
    if (!this.fixedWidthSet_) {

      this.div_.style.width = "";
    }

    if (typeof content.nodeType === "undefined") {
      this.div_.innerHTML = this.getCloseBoxImg_() + content;
    } else {
      this.div_.innerHTML = this.getCloseBoxImg_();
      this.div_.appendChild(content);
    }

    // Perverse code required to make things work with MSIE.
    // (Ensures the close box does, in fact, float to the right.)
    //
    if (!this.fixedWidthSet_) {

      this.div_.style.width = this.div_.offsetWidth + "px";
      this.div_.innerHTML = this.getCloseBoxImg_() + content;
    }

    this.addClickHandler_();
  }

  /**
   * This event is fired when the content of the InfoBox changes.
   * @name InfoBox#content_changed
   * @event
   */
  google.maps.event.trigger(this, "content_changed");
};

/**
 * Sets the geographic location of the InfoBox.
 * @param {LatLng} latlng
 */
InfoBox.prototype.setPosition = function (latlng) {

  this.position_ = latlng;

  if (this.div_) {

    this.draw();
  }

  /**
   * This event is fired when the position of the InfoBox changes.
   * @name InfoBox#position_changed
   * @event
   */
  google.maps.event.trigger(this, "position_changed");
};

/**
 * Sets the zIndex style for the InfoBox.
 * @param {number} index
 */
InfoBox.prototype.setZIndex = function (index) {

  this.zIndex_ = index;

  if (this.div_) {

    this.div_.style.zIndex = index;
  }

  /**
   * This event is fired when the zIndex of the InfoBox changes.
   * @name InfoBox#zindex_changed
   * @event
   */
  google.maps.event.trigger(this, "zindex_changed");
};

/**
 * Returns the content of the InfoBox.
 * @returns {string}
 */
InfoBox.prototype.getContent = function () {

  return this.content_;
};

/**
 * Returns the geographic location of the InfoBox.
 * @returns {LatLng}
 */
InfoBox.prototype.getPosition = function () {

  return this.position_;
};

/**
 * Returns the zIndex for the InfoBox.
 * @returns {number}
 */
InfoBox.prototype.getZIndex = function () {

  return this.zIndex_;
};

/**
 * Shows the InfoBox.
 */
InfoBox.prototype.show = function () {

  this.isHidden_ = false;
  this.div_.style.visibility = "visible";
};

/**
 * Hides the InfoBox.
 */
InfoBox.prototype.hide = function () {

  this.isHidden_ = true;
  this.div_.style.visibility = "hidden";
};

/**
 * Adds the InfoBox to the specified map. If <tt>anchor</tt>
 *  (usually a <tt>google.maps.Marker</tt>) is specified, the position
 *  of the InfoBox is set to the position of the <tt>anchor</tt>.
 * @param {Map} map
 * @param {MVCObject} [anchor]
 */
InfoBox.prototype.open = function (map, anchor) {

  if (anchor) {

    this.position_ = anchor.getPosition();
  }

  this.setMap(map);

  if (this.div_) {

    this.panBox_();
  }
};

/**
 * Removes the InfoBox from the map.
 */
InfoBox.prototype.close = function () {

  if (this.closeListener_) {

    google.maps.event.removeListener(this.closeListener_);
    this.closeListener_ = null;
  }

  if (this.eventListener1_) {

    google.maps.event.removeListener(this.eventListener1_);
    google.maps.event.removeListener(this.eventListener2_);
    google.maps.event.removeListener(this.eventListener3_);
    this.eventListener1_ = null;
    this.eventListener2_ = null;
    this.eventListener3_ = null;
  }

  if (this.contextListener_) {

    google.maps.event.removeListener(this.contextListener_);
    this.contextListener_ = null;
  }

  this.setMap(null);
};






/* END infobox.js */





var map;
var mapController;
var infoBox;
var current_category = "all";
var category_icon_base = "/media/images/categories/";
var marker_dir = "/media/images/markers/";
var current_location = "";
var current_count = "";
var geocoder;



var noah_theme = {
    
    
    _getClusterOptions: function() {
      return this._clusterOptions = this._clusterOptions || [
        { icon:       { image:            marker_dir + "cluster1.png",
                        iconAnchor:       new google.maps.Point(25, 25) },
          labelClass: 'maptimize_cluster_0'},                     
        { icon:       { image:            marker_dir + "cluster2.png",
                        iconAnchor:       new google.maps.Point(33 ,33)},
          labelClass: 'maptimize_cluster_1'},
        { icon:       { image:            marker_dir + "cluster3.png",
                        iconAnchor:       new google.maps.Point(42 ,42) },
          labelClass: 'maptimize_cluster_2'},
        { icon:       { image:            marker_dir + "cluster5.png",
                        iconAnchor:       new google.maps.Point(48, 48) },
          labelClass: 'maptimize_cluster_3'},
        { icon:       { image:            marker_dir + "cluster6.png",
                        iconAnchor:       new google.maps.Point(56, 56) },
          labelClass: 'maptimize_cluster_4'}
        ];
    },
    
    createMarker : function(marker){
        
        var options = {labelText: "",
                        labelClass: "maptimize_marker_0",
                        icon: { image: marker_dir + "leaf.png",
                                iconAnchor: new google.maps.Point(9, 49)
                               },
                        shape: {
                            type: "poly",
                            coord: [0,1,
                                    0,27,
                                    8,36,
                                    10,37,
                                    7,49,
                                    10,49,
                                    12,44,
                                    12,38,
                                    16,31,
                                    16,20,
                                    11,9,
                                    ]
                        }
                        
                       };
        return new com.maptimize.LabeledMarker(marker.getGLatLng(), options);
        
    },
    
    createCluster : function(cluster) {
      var count = cluster.getPointsCount(),
          index = parseInt(Math.log(count) / Math.log(10), 10),
          options;
      if (cluster.canExpandOnMap()) {
        options = noah_theme._getClusterOptions();
      } else {
          options = noah_theme._getClusterOptions();
        //options = myTheme._getMarkerOptions();
      }
      options = options[Math.min(options.length - 1, index)];
      options.labelText = count;
      return new com.maptimize.LabeledMarker(cluster.getGLatLng(), options);
      }
};

function open_spotting(spotting_id){
    mapController.openPopupForPointId(spotting_id);
}

function filterMap() {
  var condition = new com.maptimize.Condition(), categories = [];
  // Collect selected categories
  $("#categories_list input").each(function() {
    if (this.checked) {
      categories.push(this.value);
    }
  });
  // Create condition
  
  
  if (categories.length > 0) {
    condition.appendAnd(["category IN ?", categories]);
  }
  // Set condition
  mapController.setCondition(condition);
  // Refresh map
  mapController.refresh();
}

function clear_all(){
    $("#categories_list input").each(function() {
        this.checked = false;
    });
}

function select_all(){
    $("#categories_list input").each(function() {
        this.checked = true;
    });
}

function show_category(category_name){
    
    swap_category_icon(category_name);
    
    var condition = new com.maptimize.Condition();
    
    if(category_name != "all"){
        condition.appendAnd({category: category_name});
    }
    
    mapController.setCondition(condition);
    mapController.refresh();
    
}

function search(){
    swap_category_icon('all');
    var search_text = $('#search_field').val();
    var condition = new com.maptimize.Condition('name LIKE "' + search_text + '"');
    mapController.setCondition(condition);
    mapController.refresh();
}

function update_location_box(){
    $("#location_box").html(current_count + " " +  current_location);
}

function update_current_location(){
    
    if(window.map){
        if(window.map.getZoom() >= 8){
            geocoder.geocode({'latLng': window.map.getCenter()}, function(results, status) {
                if (status == google.maps.GeocoderStatus.OK) {
                    if(results.length > 2){
                        result_index = Math.max(results.length - 3, 2);
                        result = results[result_index];
                        current_location = "Currently viewing " + result.formatted_address + ".";
                        update_location_box();
                    }
                }
            });
        }
        else {
            current_location = "";
            update_location_box();
        }
    }
        
}

function swap_category_icon(category_name){
    if(current_category != category_name){
        if(current_category){
            old_icon_id = "#category_" + current_category;
            off_icon_url = category_icon_base + current_category + "_off.png";
            $(old_icon_id).attr("src", off_icon_url);
        }
        if(category_name){
            new_icon_id = "#category_" + category_name;
            on_icon_url = category_icon_base + category_name + "_on.png";
            $(new_icon_id).attr("src", on_icon_url);
        }
        current_category = category_name;        
    }
}



function showAddress(address) {
   if (geocoder) {
       
       geocoder.geocode( { 'address': address}, function(results, status) {
         if (status == google.maps.GeocoderStatus.OK) {
           map.setCenter(results[0].geometry.location);
           map.setZoom(6);
         } else {
           //alert("Geocode was not successful for the following reason: " + status);
         }
       });
       

   }
}

$(document).ready(function(){
    
    $.preLoadImages("/media/images/info_window.png");
    $("img[src$=_off.png]").each( function(index, element) {
        $.preLoadImages($(element).attr('src').replace('_off','_on'));
    });
    $("img[src$=_on.png]").each( function(index, element) {
        $.preLoadImages($(element).attr('src').replace('_on','_off'));
    });

    
      var mapOptions = { zoom:        2, 
                         center:      new google.maps.LatLng(18.473358501297596, 27.7734375), 
                         mapTypeId:   google.maps.MapTypeId.SATELLITE,
                         scrollwheel: false},
          map        = new google.maps.Map(document.getElementById("map"), mapOptions);
          
            var infoBox_options = {
                            disableAutoPan: false
                            ,maxWidth: 0
                            ,pixelOffset: new google.maps.Size(-100, -285)                     
                            ,zIndex: 99999
                            ,boxStyle: { 
                               background: "url('/media/images/info_window.png') no-repeat"
                              ,width: "274px"
                              ,height: "244px"
                             }
                            ,closeBoxMargin: "5px 12px 2px 2px"
                            ,closeBoxURL: "/media/images/close_button.png"
                            ,infoBoxClearance: new google.maps.Size(30, 30)
                            ,isHidden: false
                            ,pane: "floatPane"
                            ,enableEventPropagation: false
                    };

          
           infoBox = new InfoBox(infoBox_options);
          
           $('#main').ajaxError(function(event, XMLHttpRequest, ajaxOptions, thrownError) {
               console.log('Ajax Error');
            }); 
 
           var mapController_options =     {
              theme: noah_theme,
              onMarkerClicked: function(marker) {
                  var info_window_url = "/api/infowindow/"+marker.getId()+"/";
                  $.get(info_window_url, function(data, status) {
                    infoBox.close();
                    infoBox.setContent(data);
                    marker.getPosition = marker.getGLatLng;
                    infoBox.open(map, marker);
                  });
              },
              onClusterClicked: function(cluster) {
                 if (cluster.canExpandOnMap()) {
                   cluster.expandOnMap();
                 } else {
                   cluster.openPopup(function(element) {
                     cluster.requestIds(function(ids) {
                         multiHTML = '<a href="/organisms?ids=' + ids.join() + '">'
                                            + ids.length + ' spotting' + (ids.length == 1 ? '' : 's') + ' at this location.<br>';
                        
                        for(i in ids.slice(0,5)){
                            multiHTML += '<img src="/image/croppedthumb80/' + ids[i] + '" style="margin:4px 4px 0 0;width:32px;height:32px;float:left;">';
                        }
                        multiHTML += '</a>';
                        element.innerHTML = multiHTML;
                     });
                   });
                }
              } 
          };
              
              
      mapController = new com.maptimize.MapController(map, mapController_options);
      mapController.refresh();
      
      google.maps.event.addListener(map, 'zoom_changed', function() {
          infoBox.close();
        });
      
      	google.maps.event.addListener(map, "idle", function() {
                update_current_location();
            });
            
            
        geocoder = new google.maps.Geocoder();
    
      
      
      //mapController.openPopupForPointId(id);
    
    
      google.maps.event.addListener(map, 'afterRefresh', function() {
          current_count = mapController.getTotalPointsCount() + " spottings on the map.";
          update_location_box();
      });
      
      window.mapController = mapController;
      window.map = map;
      
      //filterMap();
      
      //$("#categories_list").delegate("input", "click", filterMap);
      
});

