KB.GoogleMaps = {
    mapElement:null,
    map:null,
    geo:null,
    reasons:[],
    standards : [
        ["road","rd"],
        ["street","st"],
        ["avenue","ave"],
        ["av","ave"],
        ["drive","dr"],
        ["saint","st"],
        ["north","n"],
        ["south","s"],
        ["east","e"],
        ["west","w"],
        ["expressway","expy"],
        ["parkway","pkwy"],
        ["terrace","ter"],
        ["turnpike","tpke"],
        ["highway","hwy"],
        ["lane","ln"]
    ],
    load: function(mapElement) {

        if (!GBrowserIsCompatible()) {
            alert("Sorry, the Google Maps API is not compatible with this browser");
            return;
        }

        this.mapElement=mapElement;
        this.map = new GMap(mapElement);
        this.map.addControl(new GLargeMapControl());
        this.map.addControl(new GMapTypeControl());

        // ====== Create a Client Geocoder ======
        this.geo = new GClientGeocoder();

        // ====== Array for decoding the failure codes ======
        this.reasons[G_GEO_SUCCESS]            = "Success";
        this.reasons[G_GEO_MISSING_ADDRESS]    = "Missing Address: The address was either missing or had no value.";
        this.reasons[G_GEO_UNKNOWN_ADDRESS]    = "Unknown Address:  No corresponding geographic location could be found for the specified address.";
        this.reasons[G_GEO_UNAVAILABLE_ADDRESS]= "Unavailable Address:  The geocode for the given address cannot be returned due to legal or contractual reasons.";
        this.reasons[G_GEO_BAD_KEY]            = "Bad Key: The API key is either invalid or does not match the domain for which it was given";
        this.reasons[G_GEO_TOO_MANY_QUERIES]   = "Too Many Queries: The daily geocoding quota for this site has been exceeded.";
        this.reasons[G_GEO_SERVER_ERROR]       = "Server error: The geocoding request could not be successfully processed.";
    },
    // ===== convert words to standard versions =====
    standardize: function (a) {
      for (var i=0; i<this.standards.length; i++) {
        if (a == this.standards[i][0])  {a = this.standards[i][1];}
      }
      return a;
    },

    // ===== check if two addresses are sufficiently different =====
    different: function(a,b) {
      // only interested in the bit before the first comma in the reply
      var c = b.split(",");
      b = c[0];
      // convert to lower case
      a = a.toLowerCase();
      b = b.toLowerCase();
      // remove apostrophies
      a = a.replace(/'/g ,"");
      b = b.replace(/'/g ,"");
      // replace all other punctuation with spaces
      a = a.replace(/\W/g," ");
      b = b.replace(/\W/g," ");
      // replace all multiple spaces with a single space
      a = a.replace(/\s+/g," ");
      b = b.replace(/\s+/g," ");
      // split into words
      awords = a.split(" ");
      bwords = b.split(" ");
      // perform the comparison
      var reply = false;
      for (var i=0; i<bwords.length; i++) {
        //GLog.write (standardize(awords[i])+"  "+standardize(bwords[i]))
        if (this.standardize(awords[i]) != this.standardize(bwords[i])) {reply = true}
      }
      //GLog.write(reply);
      return (reply);
    },
      // ====== Plot a marker after positive reponse to "did you mean" ======
    place:  function(lat,lng) {
        var point = new GLatLng(lat,lng);
        this.map.setCenter(point,14);
        this.map.addOverlay(new GMarker(point));
        suggestedAdsress = "";
    },

      // ====== Geocoding ======
    suggestAddress:  function(search) {
        var suggestedAdsress;
        this.map.clearOverlays();
        var point = new GLatLng('39.061849134291535', '-105.53466796875');
        var marker = new GMarker(point,{draggable:true,bouncy:true,bounceGravity:0.3});
        console.log(marker);
        this.map.addOverlay(marker);
        // ====== Perform the Geocoding ======
        this.geo.getLocations(search, function (result){
            /*
            GEvent.addListener(this.map, "moveend", function() {
              var center = this.map.getCenter();
              marker.setPoint(center);
              $('latlng').value = center.toString();
            });
            */
            if (result.Status.code == G_GEO_SUCCESS) {
              // ===== If there was more than one result, "ask did you mean" on them all =====
              if(result.Placemark){
                var placemark=result.Placemark.length ? result.Placemark[0] : result.Placemark;
                console.log(placemark);
                var point = new GLatLng(placemark.Point.coordinates[1],placemark.Point.coordinates[0]);
                //var point = new GLatLng(53.850641,-3.040175);
                this.map.setCenter(point, 11);
                marker.setPoint(point);
                $('latlng').value = point.toString();
              }
              // ===== If there was a single marker, is the returned address significantly different =====
            }
            // ====== Decode the error status ======
            else {
              alert('Could not find');
            }
          }.bind(this)
        );
    }
}