// Our global state
var initialLocation;
var newyork = new google.maps.LatLng(40.69847032728747, -73.9514422416687);
var geocoder = new google.maps.Geocoder();
var gLocalSearch;
var gMap;
var gInfoWindow;
var gSelectedResults = [];
var gCurrentResults = [];
var gSearchForm;
var mapLoaded = false;
var maxSearchTries = 5;
var searchTerms = '"body shop" "car dealer" "rental car"';

// Create our "tiny" marker icon
var gYellowIcon = new google.maps.MarkerImage(
  "http://labs.google.com/ridefinder/images/mm_20_yellow.png",
  new google.maps.Size(12, 20),
  new google.maps.Point(0, 0),
  new google.maps.Point(6, 20));
var gRedIcon = new google.maps.MarkerImage(
  "http://labs.google.com/ridefinder/images/mm_20_red.png",
  new google.maps.Size(12, 20),
  new google.maps.Point(0, 0),
  new google.maps.Point(6, 20));
var gSmallShadow = new google.maps.MarkerImage(
  "http://labs.google.com/ridefinder/images/mm_20_shadow.png",
  new google.maps.Size(22, 20),
  new google.maps.Point(0, 0),
  new google.maps.Point(6, 20));
  
  
function onLoad() {

  // Set up address search form
  $('#map_search form').submit(function() {
  
    var address = $('#map_address').val();
    geocoder.geocode({address: address}, function (results, status) {
        if (status == google.maps.GeocoderStatus.OK && results[0]) {
            // Move map 
            showMap(results[0].geometry.location);
            
            // Search
            doSearch(results[0].geometry.location, searchTerms);
            
        } else {
            alert('Geolocation failed. Try again.');
        }
    });
    
    return false;
  });
  
  // Create one InfoWindow to open when a marker is clicked.
  gInfoWindow = new google.maps.InfoWindow;
  google.maps.event.addListener(gInfoWindow, 'closeclick', function() {
    unselectMarkers();
  });
  
  // Initialize the local searcher
  gLocalSearch = new GlocalSearch();
  gLocalSearch.setResultSetSize(8);
  gLocalSearch.setSearchCompleteCallback(null, onLocalSearch);
  
  doGeolocate();
}
  
  
function doGeolocate() {
  
  var loc,
      success = function() {
        showMap(loc);
        doSearch(loc, searchTerms);
      },
      fail = function() {
        alert('Geolocation failed.');
      };
  
  // Try W3C Geolocation (Preferred)
  if(navigator.geolocation) {
    navigator.geolocation.getCurrentPosition(function(position) {
      loc = new google.maps.LatLng(position.coords.latitude,position.coords.longitude);
      success();
    }, fail);
  // Try Google Gears Geolocation
  } else if (google.gears) {
    var geo = google.gears.factory.create('beta.geolocation');
    geo.getCurrentPosition(function(position) {
      loc = new google.maps.LatLng(position.latitude,position.longitude);
      success();
    }, fail);
  }
}

function showMap(loc) {

  // Just recenter map if it's already created.
  if (gMap) {
    gMap.setCenter(loc);
    
    return;
  }
  
  // Initialize the map with default UI.
  gMap = new google.maps.Map(document.getElementById("map"), {
    center: loc,
    zoom: 13,
    mapTypeId: 'roadmap'
  });
}

function onLocalSearch() {
  if (!gLocalSearch.results) return;
  var searchWell = document.getElementById("searchwell");

  // Clear the map and the old search well
  searchWell.innerHTML = "";
  for (var i = 0; i < gCurrentResults.length; i++) {
    gCurrentResults[i].marker().setMap(null);
  }
  // Close the infowindow
  gInfoWindow.close();

  gCurrentResults = [];
  for (var i = 0; i < gLocalSearch.results.length; i++) {
    gCurrentResults.push(new LocalResult(gLocalSearch.results[i]));
  }

  var attribution = gLocalSearch.getAttribution();
  if (attribution) {
    document.getElementById("searchwell").appendChild(attribution);
  }

  // Move the map to the first result
  var first = gLocalSearch.results[0];
  gMap.setCenter(new google.maps.LatLng(parseFloat(first.lat),
                                        parseFloat(first.lng)));
}

function unselectMarkers() {
  for (var i = 0; i < gCurrentResults.length; i++) {
    gCurrentResults[i].unselect();
  }
}

function doSearch(loc, terms) {
  var searchTries = maxSearchTries,
      searchCb = function() {
          try {
              gLocalSearch.setCenterPoint(loc);
              gLocalSearch.execute(terms);
          } catch (e) {
              searchTries--;
              // Repeat until it works.
              if (searchTries > 0) {
                  setTimeout(function() { searchCb(); }, 100);
              }
          }
      };
  searchCb();
}


// A class representing a single Local Search result returned by the
// Google AJAX Search API.
function LocalResult(result) {
  var me = this;
  me.result_ = result;
  me.resultNode_ = me.node();
  me.marker_ = me.marker();
  google.maps.event.addDomListener(me.resultNode_, 'mouseover', function() {
    // Highlight the marker and result icon when the result is
    // mouseovered.  Do not remove any other highlighting at this time.
    me.highlight(true);
  });
  google.maps.event.addDomListener(me.resultNode_, 'mouseout', function() {
    // Remove highlighting unless this marker is selected (the info
    // window is open).
    if (!me.selected_) me.highlight(false);
  });
  google.maps.event.addDomListener(me.resultNode_, 'click', function() {
    me.select();
  });
  document.getElementById("searchwell").appendChild(me.resultNode_);
}

LocalResult.prototype.node = function() {
  if (this.resultNode_) return this.resultNode_;
  return this.html();
};

// Returns the GMap marker for this result, creating it with the given
// icon if it has not already been created.
LocalResult.prototype.marker = function() {
  var me = this;
  if (me.marker_) return me.marker_;
  var marker = me.marker_ = new google.maps.Marker({
    position: new google.maps.LatLng(parseFloat(me.result_.lat),
                                     parseFloat(me.result_.lng)),
    icon: gYellowIcon, shadow: gSmallShadow, map: gMap});
  google.maps.event.addListener(marker, "click", function() {
    me.select();
  });
  return marker;
};

// Unselect any selected markers and then highlight this result and
// display the info window on it.
LocalResult.prototype.select = function() {
  unselectMarkers();
  this.selected_ = true;
  this.highlight(true);
  gInfoWindow.setContent(this.html(true));
  gInfoWindow.open(gMap, this.marker());
};

LocalResult.prototype.isSelected = function() {
  return this.selected_;
};

// Remove any highlighting on this result.
LocalResult.prototype.unselect = function() {
  this.selected_ = false;
  this.highlight(false);
};

// Returns the HTML we display for a result before it has been "saved"
LocalResult.prototype.html = function() {
  var me = this;
  var container = document.createElement("div");
  container.className = "unselected";
  container.appendChild(me.result_.html.cloneNode(true));
  return container;
}

LocalResult.prototype.highlight = function(highlight) {
  this.marker().setOptions({icon: highlight ? gRedIcon : gYellowIcon});
  this.node().className = "unselected" + (highlight ? " red" : "");
}

GSearch.setOnLoadCallback(onLoad);
