function Locator() {
  var self = this;
  var api_key = 'ABQIAAAA1GcWAoQ0wiVCaYlRooKYbxTAKNqnB9lF7PQ880_qvbTqkgcNzRRMC45jEWr1NtveD4Awb0vlCuEhqg';
  this.location_page = this.root;
  
  this.g_map = this.location_page.find('#g_map')[0];
  this.locations = this.location_page.find('div.left div.results dl');
  this.geocode_elements = this.locations.find('dd.geocode');
  this.events_listing = this.location_page.find('div.right div.events');
  this.location_filter = this.location_page.find('.filter form');

  this.geocodes = new Array();
  this.markers = new Array();
  
  var locations_tabs = new Runes({
    basins : this.location_page.find('div.basins').children(),
    change_wrapper_height : false
  },{
    tabs : this.location_page.find('div.left div.pagination a.tab'),
    switch_method : 'two_slide_switch'
  }).start_up();
  
  
  var rune_results = new Runes({
    basins : this.location_page.find('div.results').children().children()
  },{
    sliders : this.location_page.find('div.left div.pagination a').not('a.tab'),
    switch_method : 'vertical_all_slide',
    auto : false,
    delay : 0
  }).start_up();
  
  this.destroy_map = function() {
    google.maps.Unload();
  }
  
  this.reload_locations = function(html) {
    self.location_page.find('div.basins div.results').children().children().unbind();
    self.location_page.find('div.basins div.results').children().html(html);
    self.location_page.find('div.left div.pagination a.tab').eq(0).trigger('click');
    rune_results.basins = self.location_page.find('div.basins div.results').children().children();
    self.location_page.find('div.basins div.results').children().css('top', '0');
    rune_results.start_up();
    self.redraw_map();
  }

  function bind_joint_links() {
    self.location_page.find('a.joint_name').bind('click', self.joint_link_clicked);
  }

  this.joint_link_clicked = function(e) {
    e.preventDefault();
    var joint_name = $(e.currentTarget);
    var location = joint_name.closest('dl');
    highlight_location(index_of_location(location));
    self.get_events(id_of_location(location), joint_name.html());
    return false;
  }
  
  this.map_change = function(e) {
    e.preventDefault();
    var me = $(e.currentTarget);
    $.ajax({
  		type: "GET",
  		url: me.attr('action'),
  		data: me.serialize() + '&ajax=true',
  		success: self.reload_locations
  	});
  }
  
  this.cache_geocodes = function() {
    self.locations = self.location_page.find('div.left div.results dl');
    self.geocode_elements = self.locations.find('dd.geocode');
    self.geocodes = new Array();
    self.markers = new Array();
    for (var i = 0; i < self.geocode_elements.length; i++) {
      self.geocodes[i] = new google.maps.LatLng(Number(self.geocode_elements.eq(i).children('span.latitude').html()), Number(self.geocode_elements.eq(i).children('span.longitude').html()));
      self.markers[i] = new google.maps.Marker(self.geocodes[i]);
    }
  }
  
  this.inner_map_bubble = function(content) {
    return content;
  }
  
  this.reload_events = function(data) {
    self.events_listing.html(data);
    var tabs = self.events_listing.find('.event_type_tabs li');
    var single_type_tabs = tabs.filter('.select_one');
    var all_types_tab = tabs.filter('.select_all');
    var events = self.events_listing.find('.content .single');
    single_type_tabs.bind('click', function (e) {
        e.preventDefault();

        tabs.removeClass('selected_tab');
        events.hide();

        var tab = $(e.currentTarget);
        tab.addClass('selected_tab');
        var to_show = events.filter('.' + tab.attr('event_type'));
        to_show.show();
        size_events_container(to_show.length);
    });
    all_types_tab.bind('click', function (e) {
        e.preventDefault();

        tabs.removeClass('selected_tab');
        events.show();
        size_events_container(events.length);
        all_types_tab.addClass('selected_tab');
    });

    size_events_container(events.length);
    self.events_listing.removeClass('loading');
  }

  function size_events_container(num_events) {
    var container = self.events_listing.find('.content');
    if (num_events == 0) {
      container.hide();
    } else {
      container.show();
      var width = 0;
      container.children().each(function(i, child) {
          width += child.clientLeft + child.offsetWidth;
      });
      container.width(width);
    }
  }
  
  this.get_events = function(location_id, joint_name) {
    if (joint_name == undefined) {
      joint_name = '';
    }
    self.events_listing.html('<h3>Loading events...</h3>');
    self.events_listing.addClass('loading');
    $.ajax({
  		type: "GET",
  		url: '/events/tabbed',
  		data: {
  		  location : location_id,
                  joint_name : joint_name,
  		  ajax : true
  		},
  		success: self.reload_events
  	});
  }
  
  this.maker_marker = function(iter) {
    google.maps.Event.addListener(self.markers[iter], "click", function() {
      highlight_location(iter);
      rune_results.scroll_to(iter);
      self.get_events(id_of_location(self.locations.eq(iter)));
    });
   
    self.locations.eq(iter).bind('click', function(e) {
      google.maps.Event.trigger(self.markers[iter], "click");
    });
    
    self.g_map.addOverlay(self.markers[iter]);
  }

  function highlight_location(location_index) {
    var latlng = self.geocodes[location_index];
    self.locations.removeClass('selected');
    self.locations.eq(location_index).addClass('selected');
    self.g_map.panTo(latlng, true);
    self.g_map.openInfoWindowHtml(latlng, '<dl class="results">' + self.locations.eq(location_index).clone().html() + '</dl>')
  }

  function id_of_location(location) {
    return Number(location.find('dd.location_info span').html());
  }

  function index_of_location(location) {
    return location.prevAll().length;
  }
  
  this.redraw_map = function() {
    self.g_map.clearOverlays();
    
    self.cache_geocodes();
    self.g_map.setCenter(self.geocodes[0], 11);
    
    for (var i = 0; i < self.markers.length; i++) {
      self.maker_marker(i);
    }
  }
  
  this.build_map = function() {
    
    self.g_map = new google.maps.Map2(self.g_map);
    var customUI = self.g_map.getDefaultUI();
    customUI.zoom.scrollwheel = false;
    self.g_map.setUI(customUI);
    self.g_map.enableContinuousZoom();
    
    self.redraw_map();
  }
  
  this.initiate_map = function() {
    google.load("maps", "2", {"callback" : self.build_map});
  }
  
  this.put_in_filiters = function(json) {
    var amenity_filter = '';
    for (var i = 0; i < json.length; i++) {
      amenity_filter += '<img src="/images/global/icons/amenities/' + json[i].short_name.replace(/ /g, '_').replace(/\'/g, '').replace(/\&/g, 'and').toLowerCase() + '.png" alt="' + json[i].short_name + '" />';
      amenity_filter += '<label>' + json[i].short_name + '</label>';
      amenity_filter += '<input type="checkbox" ';
      amenity_filter += 'name="tags[' + json[i].namespace + '][]" ';
      amenity_filter += 'value="' + json[i].short_name + '" /> <br />';
    }
    self.location_filter.children('fieldset.amenities').children('div').append(amenity_filter);
  }
  
  this.set_up_filters = function() {
    $.ajax({
      url: '/tags',
      data: {
        namespace : 'amenities'
      },
      dataType: 'json',
      success: self.put_in_filiters
    });
  }
  
  this.start_up = function() {
    $.getScript('http://www.google.com/jsapi?key=' + api_key, self.initiate_map);
    self.set_up_filters();
    self.location_filter.bind('submit', self.map_change);
    bind_joint_links();
    $(window).bind('unload', self.destroy_map);
  }
  
  return this;
}

