codekitchen = {
}
codekitchen.mapping = {
  layers: {},
  map: null,
  allowedBounds: null,
  sidebar_control: null,
  has_searched: false,
  logged_in: false,
  first_search: true,
  SidebarControlClass: function() {},
  initialize: function() {
    if(!GBrowserIsCompatible()) {
      window.location = "/browser_not_supported.html"
      return
    }
    this.map = new GMap2($('#map')[0])
    
    // misc setup
    $("#error-message").ajaxError(function(e,r,s){
      $('p', this)[0].innerHTML = r.responseText
      $(this).fadeIn('fast')
      codekitchen.mapping.hideSearchingMessage()
    })
    $(".toggle-target-div").click(function() {
      $("#"+$(this).attr('toggle-target')).toggle('fast')
      return false
    })
    $("#search-bar form").submit(function() {
      var query = $.trim($("#search-query").val())
      if (query.match(/^[\d]{5}$/)) {
        // zip code search
        codekitchen.mapping.searchByZip(query)
      } else {
        // city search
        codekitchen.mapping.searchByCity(query)
      }
      return false
    })
    $("#community-select").change(function() {
      var id = $(this).val()
      var listing = null
      $.each(codekitchen.mapping.layers, function() {
        $.each(this.markers, function() {
          if (this.listing.id == id)
            listing = this
        })
      })
      if (listing) {
        codekitchen.mapping.map.setCenter(listing.getPoint(),11, codekitchen.mapping.first_search ? G_SATELLITE_MAP : null)
        codekitchen.mapping.first_search = false
        setTimeout(function() { listing.showInfo.apply(listing) }, 13)
      }
    })
    tb_init("a.overlay")
    
    // Limit zoom range and movement bounds
    if (!this.logged_in) {
      this.allowedBounds = new GLatLngBounds(new GLatLng(37.00255, -114.04907), new GLatLng(41.98399, -109.05029))
      $.each(this.map.getMapTypes(), function(){
        if(this.getMinimumResolution) {
          this.getMinimumResolutionOriginal = this.getMinimumResolution
          this.getMinimumResolution = function(ll) {
            return Math.max(7, this.getMinimumResolutionOriginal(ll));
          }
        }
      })
    }
    
    // setup layers
    $("input:checkbox[@layer-id]").change(function() {
      var layer_id = $(this).attr('layer-id')
      if ($(this).is(':checked')) codekitchen.mapping.showLayer(layer_id)
      else                        codekitchen.mapping.hideLayer(layer_id)
    })
    $("input:checkbox:checked[@layer-id]").change()
    
    GEvent.addListener(this.map, 'move', function() {codekitchen.mapping.checkBounds()})
    // GEvent.addListener(this.map, 'infowindowclose', function() { $("#community-select").val("0") })
    /* Fake GControl class that takes up the same area as the sidebar,
       So that the info window doesn't appear under the sidebar. */
    this.SidebarControlClass.prototype = new google.maps.Control()
    this.SidebarControlClass.prototype.initialize = function(map) {
      d(this)
      this.cnt = document.createElement('div')
      this.cnt.style.width = this.ck_w ? this.ck_w : '225px'
      this.cnt.style.height = this.ck_h ? this.ck_h : '360px'
      map.getContainer().appendChild(this.cnt)
      return this.cnt
    }
    this.SidebarControlClass.prototype.getDefaultPosition = function() {
      return new google.maps.ControlPosition(G_ANCHOR_TOP_LEFT, new GSize(0,0))
    }
    /* invisible control hack -- Don't let the info window appear under the sidebar */
    this.sidebar_control = [new this.SidebarControlClass(), new this.SidebarControlClass()]
    this.sidebar_control[1].ck_w = '847px'
    this.sidebar_control[1].ck_h = '25px'
    this.map.addControl(this.sidebar_control[0])
    this.map.addControl(this.sidebar_control[1])
    this.map.setCenter(new GLatLng(40.12,-112.28),7,G_NORMAL_MAP)
    this.map.addControl(new GSmallMapControl(), new GControlPosition(G_ANCHOR_TOP_LEFT, new GSize(240, 25+8)))
    this.map.addControl(new GMapTypeControl(), new GControlPosition(G_ANCHOR_TOP_RIGHT, new GSize(8, 25+8)))
    this.map.enableScrollWheelZoom()
    this.map.enableContinuousZoom()
    $(document).unload(function() { GUnload() })

    /* test layer */
    var copyCollection = new GCopyrightCollection('chart');
    var copyright = new GCopyright(1, new GLatLngBounds(new GLatLng(-90, -180), new GLatLng(90,180)), 0, "&copy;REWDAD");
    copyCollection.addCopyright(copyright);
    var tileLayers = [new GTileLayer(copyCollection, 15, 16)];
    tileLayers[0].getTileUrl = function(pos,z) {
      return "/images/layer"+z+"/"+z+"_"+pos.x+"_"+pos.y+".gif";
    }
    var custommap = new GMapType(tileLayers, new GMercatorProjection(17), "CC", {errorMessage: "Ohcrap"});
    this.map.addMapType(custommap);

    
    this.initialize_admin_mode()
  },
  initialize_admin_mode: function() {},
  // loadLayer will happily reload an already-loaded layer
  loadLayer: function(id, show) {
    var self = this
    if (arguments.length < 2) show = true
    d("loading layer " + id)
    $.getJSON('/listings/json', {layer_id:id}, function(json) {
      var listings = json.listings
      if (!listings || listings.length < 1) return
      if (self.layers[id]) self.hideLayer(id)
      var icon = new google.maps.Icon()
      icon.iconSize = new GSize(32,32)
      icon.image = json.icon
      icon.iconAnchor = new GPoint(16,16)
      icon.infoWindowAnchor = new GPoint(16,8)
      var mgr = new MarkerManager(self.map)
      var markers = $.map(listings, function(e) { return self.createListing(icon,e,id) })
      self.layers[id] = {title: json.title, mgr: mgr, markers: markers, shown: false, icon:icon, is_homes: json.is_homes}
      if (show) self.showLayer(id)
    })
  },
  showLayer: function(id) {
    // if not loaded, the layer will be loaded via AJAX and shown as soon as it's available
    var layer = this.layers[id]
    if (!layer) {
      this.loadLayer(id)
      return
    }
    d("showing layer " + id)
    if (layer.shown) return
    layer.mgr.addMarkers(layer.markers, ((this.logged_in || layer.is_homes) ? 1 : 10))
    layer.mgr.refresh()
    layer.shown = true
  },
  hideLayer: function(id) {
    var layer = this.layers[id]
    if (!layer || !layer.shown) return
    layer.mgr.clearMarkers()
    layer.shown = false
    d("hiding layer " + id)
  },
  
  // Searching
  searchByZip: function(zip) {
    var self = this
    this.showSearchingMessage()
    $.getJSON('/listings/searchByZip', {postalcode:zip}, function(json) {
      if (!(json.lng && json.lat)) throw("got bad response")
      self.centerOnBounds(json.lat, json.lng)
      self.hideSearchingMessage()
    })
  },
  searchByCity: function(city) {
    var self = this
    this.showSearchingMessage()
    $.getJSON('/listings/searchByCity', {city:city}, function(json) {
      if (!(json.lat_min)) throw("got bad response")
      self.centerOnBounds(json.lat_min, json.lng_min, json.lat_max, json.lng_max)
      if (json.lat_min == json.lat_max && json.lng_min == json.lng_max && self.logged_in)
        self.createMarkerAtPoint(json.lat_min, json.lng_min, json.name, json.zip, json.street)
      self.hideSearchingMessage()
    })
  },
  showSearchingMessage: function() {
    $("#community-select").attr('disabled', 'disabled')
    this.searchQuery = $("#search-query").val()
    $("#search-query").attr('disabled', 'disabled').val("Searching...")
  },
  hideSearchingMessage: function() {
    $("#community-select").removeAttr("disabled")
    $("#search-query").removeAttr('disabled').val(this.searchQuery)
  },
  
  lBuffer: 0.023,
  centerOnBounds: function(lat_min, lng_min, lat_max, lng_max) {
    if (!lat_max) { lat_max = lat_min; lng_max = lng_min; }
    var centerPoint = new google.maps.LatLng(lat_max-(lat_max-lat_min)/2, lng_max-(lng_max-lng_min)/2)
    var bounds = new google.maps.LatLngBounds(new google.maps.LatLng(lat_min - this.lBuffer, lng_min - this.lBuffer), new google.maps.LatLng(lat_max + this.lBuffer, lng_max + this.lBuffer))
    var zoom = this.map.getBoundsZoomLevel(bounds)
    this.map.setCenter(centerPoint, zoom, this.first_search ? G_SATELLITE_MAP : null)
    this.first_search = false
  },
  
  // Thx econym.demon.co.uk
  checkBounds: function() {
    if (!this.allowedBounds) return;
    // Perform the check and return if OK
    if (this.allowedBounds.contains(this.map.getCenter())) {
      return;
    }
    // It`s not OK, so find the nearest allowed point and move there
    var C = this.map.getCenter();
    var X = C.lng();
    var Y = C.lat();

    var AmaxX = this.allowedBounds.getNorthEast().lng();
    var AmaxY = this.allowedBounds.getNorthEast().lat();
    var AminX = this.allowedBounds.getSouthWest().lng();
    var AminY = this.allowedBounds.getSouthWest().lat();

    if (X < AminX) {X = AminX;}
    if (X > AmaxX) {X = AmaxX;}
    if (Y < AminY) {Y = AminY;}
    if (Y > AmaxY) {Y = AmaxY;}
    this.map.setCenter(new GLatLng(Y,X));
  }
}
function loadMM() {
  if (typeof GBounds == "undefined") {
    setTimeout(loadMM, 20);
  } else {
    var headID = document.getElementsByTagName("head")[0];         
    var newScript = document.createElement('script');
    newScript.type = 'text/javascript';
    newScript.src = '/javascripts/markermanager.js';
    headID.appendChild(newScript);
    setTimeout(initMap, 20);
  }
}
function initMap() {
  if (typeof MarkerManager == "undefined") {
    setTimeout(initMap, 20);
  } else {
    codekitchen.mapping.initialize();
  }
}
google.load("maps", "2")
google.setOnLoadCallback(loadMM)

if (window.$development_mode) {
  var d = console.debug
  var m = codekitchen.mapping
} else {
  var d = function(){}
}
