/**
 * @class
 * Support functions used for a map sidebar controls
 */
ta.maps.Sidebar = {
  icons: {
    "hotel": "/img2/maps/icons/pinHotel.gif",
    "restaurant": "/img2/maps/icons/pinRestaurant.gif",
    "attraction": "/img2/maps/icons/pinThingToDo.gif"
  },

  _addHotelRestaurantAttraction: function(type, number) {
    var map = ta.retrieve('maps.map');

    var zft = ta.retrieve('zft') || [];
    if (!zft.contains(number)) {
      zft.push(number);
      ta.store('zft', zft);
    }
    ta.servlet.HACSearch.filtersChanged();
    if (map) map.showType(type);
  },

  hotels: function(event, elmt) {
    var map = ta.retrieve('maps.map');

    var zft = ta.retrieve('zft') || [];
    if ($(elmt).checked) {
      ta.maps.Sidebar._addHotelRestaurantAttraction('hotel', 1);
    }
    else {
      zft.remove(1);
      ta.store('zft', zft);
      map.hideType('hotel');
    }

    ta.servlet.HACSearch.filter.update();
    return true;
  },

  restaurants: function(event, elmt) {
    var map = ta.retrieve('maps.map');

    var zft = ta.retrieve('zft') || [];
    if ($(elmt).checked) {
      ta.store('lma', 'BCACMap_Restaurants');
      ta.maps.Sidebar._addHotelRestaurantAttraction('restaurant', 3);
    }
    else {
      zft.remove(3);
      ta.store('zft', zft);
      map.hideType('restaurant');
    }

    ta.servlet.HACSearch.filter.update();
    return true;
  },

  attractions: function(event, elmt) {
    var map = ta.retrieve('maps.map');

    var zft = ta.retrieve('zft');
    if ($(elmt).checked) {
      ta.store('lma', 'BCACMap_ThingsToDo');
      ta.maps.Sidebar._addHotelRestaurantAttraction('attraction', 2);
    }
    else {
      zft.remove(2);
      ta.store('zft', zft);
      map.hideType('attraction');
    }

    ta.servlet.HACSearch.filter.update();
    return true;
  },

  /**
   * Object storing data for each landmark type.
   */
  landmarkData: {
    "coffee": {query: "Coffee", iconIndex: 4, action: 'BCACMap_Coffee'},
    "copy": {query: "Copy Center", iconIndex: 5, action: 'BCACMap_Copy'},
    "shipping": {query: "Fedex, Shipping", iconIndex: 6, action: 'BCACMap_Shipping'},
    "rail": {query: "Rail stations", iconIndex: 10, action: 'BCACMap_Rail'}
  },

  _landmarkSearchCallback: function(type, searcher, click) {
    var map = ta.retrieve('maps.map');
    var bounds = map.mapBounds();

    var lst = [];
    for (var i = 0; i < searcher.results.length; i++) {
      var x = searcher.results[i];
      var contents = new Element('div');
      var query = x.titleNoFormatting;
      if (x.addressLines) {
        x.addressLines.each(function(l) {
          contents.adopt(new Element('div').setText(l));
        });
        query = x.addressLines.join(", ");
      }
      contents.adopt(new Element('a', { 'href': map_gmaps_address_url + encodeURIComponent(query) }).setText(map_drivingdirections));

      var opt = {
        lat: x.lat,
        lng: x.lng,
        customHover: {
          title: x.titleNoFormatting,
          titleUrl: x.url,
          contents: contents
        }
      };
      var point = new GLatLng(x.lat, x.lng);
      if (bounds.containsLatLng(point)) {
        lst.push(opt);
      }
    }

    map.replaceMarkers(lst, type,
                       $merge(ta.maps.MARKER_HOTEL, {
                         anchorX: 5, anchorY: 30,
                         pinIndex: 7, iconIndex: ta.maps.Sidebar.landmarkData[type].iconIndex
                       }));
  },

  _landmarkSearch: function(type, click) {
    var map = ta.retrieve('maps.map');

    if (!$defined(google.search.LocalSearch)) {
      ta.maps.Sidebar._landmarkSearch.delay(1000, this, [type,click]);
      return;
    }

    var searcher = new google.search.LocalSearch();
    searcher.setCenterPoint(map.mapCenter());
    searcher.setResultSetSize(google.search.Search.LARGE_RESULTSET);
    searcher.setSearchCompleteCallback(this, function() { ta.maps.Sidebar._landmarkSearchCallback(type, searcher, click); });

    var fn = function() {searcher.execute(ta.maps.Sidebar.landmarkData[type].query);};
    fn.delay(250);
  },

  addLandmark: function(type) {
    var landmarks = ta.retrieve('maps.landmarks');
    var map = ta.retrieve('maps.map');

    if (map) map.showType(type);
    if (!landmarks.contains(type)) {
      landmarks.push(type);
    }
    ta.store('maps.landmarks', landmarks);
    ta.maps.Sidebar._landmarkSearch(type, 1);
  },

  /**
   * Event handler called when a landmark that involves Google Local Search is clicked,
   * and handles either hiding the existing markers or calling out to Google and putting
   * the search results on the map.
   */
  toggleLandmark: function(event, elmt) {

    var map = ta.retrieve('maps.map');
    var landmarks = ta.retrieve('maps.landmarks');
    var type = elmt.getProperty('id').substr(8);

    if ($(elmt).checked) {
      new Ajax('/ActionRecord?action=' + ta.maps.Sidebar.landmarkData[type].action).request();
      ta.maps.Sidebar.addLandmark(type);
    }
    else {
      landmarks.remove(type);
      ta.store('maps.landmarks', landmarks);
      map.hideType(type);
    }

    ta.servlet.HACSearch.filter.update();

    return true;
  },

  togglePOI: function(event, elmt) {

    var map = ta.retrieve('maps.map');
    var marker = elmt.marker;
    var type = elmt.poiType;
    var pois = ta.retrieve('maps.' + type);
    var point = null;
    var iconIndex = -1;
    var source = '';

    if (type == 'airports') {
      iconIndex = 9;
      source = 'BCACMap_Airport';
    }
    else {
      iconIndex = 8;
      source = 'BCACMap_ConventionCtr';
    }

    if ($(elmt).checked) {
      var found = false;
      if (!pois.contains(marker)) {
        pois.push(marker);
        point = new GLatLng(marker.lat, marker.lng);
      }
      new Ajax('/ActionRecord?action=' + source).request();
    }
    else {
      pois.remove(marker);
    }

    if (map) {
      map.replaceMarkers(pois, type,
                         $merge(ta.maps.MARKER_HOTEL, {
                           anchorX: 5, anchorY: 30,
                           pinIndex: 7,
                           iconIndex: iconIndex
                         }));

      if (point != null) {
        map.zoomAndPanToFit(point.lat(), point.lng());
      }

      map.showType(type);
    }
    ta.servlet.HACSearch.filter.update();
  },

  _openAccordion: function(accordionElmt, poiType, prefix) {
    if (!accordionElmt.hasClass('on')) {
      accordionElmt.toggleClass('on');
    }

    if (!ta.retrieve('maps.' + poiType)) {
      ta.store('maps.' + poiType, []);      
    }

    var listElmt = accordionElmt.getNext("div");
    listElmt.removeClass("hidden");

    if (!listElmt.init) {
      var pois = ta.retrieve('maps.nearbyPOIs')[poiType];
      if (pois != null) {
        pois.markers.each(function(p) {
          var input = new Element('input', {'type': 'checkbox',
                                            'name': prefix + p.locId,
                                            'id':   prefix + p.locId })
                              .addEvent('click', function(e) { ta.call('ta.maps.Sidebar.togglePOI', e); });
          var label = new Element('label', {'for': prefix + p.locId}).setText(p.customHover.title);
          var divContainer = new Element('div', {'class': 'poiContainer'});
          var div1 = new Element('div', {'class': 'checkbox'});
          var div2 = new Element('div', {'class': 'label'});
          div1.adopt(input);
          div2.adopt(label);

          input.marker = p;
          input.poiType = poiType;
          divContainer.adopt(div1);
          divContainer.adopt(div2);
          listElmt.adopt(divContainer);
        });
      }
      listElmt.init = true;
    }
  },

  _closeAccordion: function(accordionElmt, type) {
    if (accordionElmt.hasClass('on')) {
      accordionElmt.toggleClass('on');
    }

    var listElmt = $(accordionElmt.getNext("div"));
    listElmt.addClass("hidden");
  },

  /**
   * Event handler called when the airports accordion is clicked on, which handles
   * either opening or closing the accordion.  If opening the accordion, it automatically
   * closes the convention centers accordion if open.
   */
  toggleAirports: function(event, elmt) {
    if (elmt.getTag() != "div") {
      elmt = elmt.getParent("div");
    }

    if (!elmt.hasClass('on')) {
      ta.maps.Sidebar._closeAccordion($('toggle_convention_centers'), 'conventionCenters');
      if($('toggle_nearby_cities')) ta.maps.Sidebar._closeAccordion($('toggle_nearby_cities'), 'nearbyCities');
      ta.maps.Sidebar._openAccordion($('toggle_airports'), 'airports', 'airport_');
    }
    else {
      ta.maps.Sidebar._closeAccordion($('toggle_airports'), 'airports');
    }

    ta.servlet.HACSearch.filter.update();
  },

  /**
   * Event handler called when the convention centers accordion is clicked on, which handles
   * either opening or closing the accordion.  If opening the accordion, it automatically
   * closes the airports accordion if open.
   */
  toggleConventionCenters: function(event, elmt) {
    if (elmt.getTag() != "div") {
      elmt = elmt.getParent("div");
    }

    if (!elmt.hasClass('on')) {
      ta.maps.Sidebar._closeAccordion($('toggle_airports'), 'airports');
      if($('toggle_nearby_cities')) ta.maps.Sidebar._closeAccordion($('toggle_nearby_cities'), 'nearbyCities');
      ta.maps.Sidebar._openAccordion($('toggle_convention_centers'), 'conventionCenters', 'convention_center_');
    }
    else {
      ta.maps.Sidebar._closeAccordion($('toggle_convention_centers'), 'conventionCenters');
    }

    ta.servlet.HACSearch.filter.update();
  },

  toggleNearbyCities: function(event, elmt) {
    if (elmt.getTag() != "div") {
      elmt = elmt.getParent("div");
    }

    if (!elmt.hasClass('on')) {
      ta.maps.Sidebar.openNearbyCities();
    }
    else {
      ta.maps.Sidebar._closeAccordion($('toggle_nearby_cities'), 'nearbyCities');
    }

    ta.servlet.HACSearch.filter.update();
  },

  openNearbyCities: function(event, elmt) {
    ta.maps.Sidebar._closeAccordion($('toggle_airports'), 'airports');
    ta.maps.Sidebar._closeAccordion($('toggle_convention_centers'), 'conventionCenters');
    ta.maps.Sidebar._openAccordion($('toggle_nearby_cities'), 'nearbyCities', 'cities_');
  },


  /**
   * Event handler called when the map is morphed.
   */
  mapMorphed: function(idx, map) {
    if (idx == 0) {  // changing to thumbnail
      var landmarks = ta.retrieve('maps.landmarks');
      landmarks.each(function(type) {
        map.hideType(type);
      });
      $('MAPPROMO').setStyle('display', 'block');
      new Ajax('/ActionRecord?action=BCACMap_close').request();
    }
    else if (idx == 1) {  // changing to large map
      var landmarks = ta.retrieve('maps.landmarks');
      landmarks.each(function(type) {
        map.showType(type);
      });
      $('MAPPROMO').setStyle('display', 'none');
      var source = ta.remove('maps.morphBigSource') || 't';
      ta.store('lma', 'BCACMap_' + source + '_open');

    }

    var ret = ta.servlet.HACSearch.mapMorphed(idx, map);

    if (idx == 1 && ta.has('maps.queuedSidebar')) {
      var queuedFunctions = ta.remove('maps.queuedSidebar');
      queuedFunctions.each(function(fn) { fn(); });
    }

    return ret;
  },

  /**
   * Event handler called when the map is moved.
   */
  mapMoved: function(zoomChanged, zoom) {
    var landmarks = ta.retrieve('maps.landmarks');
    landmarks.each(function(type) {
      ta.maps.Sidebar._landmarkSearch(type);
    });

    return ta.servlet.HACSearch.mapMoved(zoomChanged, zoom);
  },

  /**
   * Event handler called when the map is zoomed.
   */
  mapZoomed: function(oldZoom, newZoom) {
    var landmarks = ta.retrieve('maps.landmarks');
    landmarks.each(function(type) {
      ta.maps.Sidebar._landmarkSearch(type);
    });

    return ta.servlet.HACSearch.mapZoomed(oldZoom, newZoom);
  },

  /**
   * Event handler called when the map is reset.
   */
  mapReset: function() {
    var landmarks = ta.retrieve('maps.landmarks');
    landmarks.each(function(type) {
      ta.maps.Sidebar._landmarkSearch(type);
    });
    // for non-business center, the location bar gets cleared by a map reset
    if (pageServlet != 'BusinessCenter') {      
      ta.maps.Sidebar._clearLocation();
    }

    return ta.servlet.HACSearch.mapReset();
  },

  _removeLocation: function() {
    var map = ta.retrieve('maps.map');
    map.hideType('location');
  },
  
  addLocationPopup: function(event, elmt) {
    if ($("add_location_text").getText() == map_removeaddress) {
      ta.maps.Sidebar._removeLocation();
      $("add_location_text").setText(map_addaddress);                
    }
    else {
      $('add_location').removeClass('hidden');
    }
  },

  closeAddLocationPopup: function(event, elmt) {
    $('add_location').addClass('hidden');
    $('add_location_input').value = map_addresstemplate;
    $('add_location_input').addClass('unfocused');
    $("add_location_error").setText('');
    $("add_location_error").addClass("hidden");
    $("add_location_header").removeClass("error");
  },

  clearAddLocationBox: function(event, elmt) {
    if (elmt.hasClass('unfocused')) {
      elmt.value = '';
      elmt.removeClass('unfocused');
    }
  },

  _addLocation: function(address) {
    var map = ta.retrieve('maps.map');
    // if we aren't using popup version of add location, we need to write
    // the address into the search box
    if (!$("add_location")) {
      var input = $("add_location_input");
      input.value = address;
      input.removeClass("unfocused");
    }

    // send off to geocoding
    var geocoder = new GClientGeocoder();
    geocoder.setViewport(map.mapBounds());
    geocoder.getLatLng(address, ta.maps.Sidebar._addLocationCallback);
  },

  addLocation: function(event, elmt) {
    var text = $("add_location_input").value;
    // if not popup version of add location, then empty address means remove marker
    if (!$("add_location") && (text.length == 0 || text == map_enteraddress)) {
      ta.maps.Sidebar._clearLocation();
      ta.servlet.HACSearch.filter.update();
      return false;
    }
    if (text != map_enteraddress) {
        ta.store('maps.address', text);
        ta.maps.Sidebar._addLocation(text);
        new Ajax('/ActionRecord?action=BCACMap_MapIt').request();
        ta.servlet.HACSearch.filter.update();
    }
    return false;
  },
  
  _clearLocation: function() {
    ta.maps.Sidebar._removeLocation();
    ta.maps.Sidebar._clearLocationError();
    var input = $("add_location_input");
    input.value = map_enteraddress;
    input.addClass("unfocused");
  },
  
  _setLocationError: function(errorMsg) {
    $("add_location_error").setText(errorMsg);
    $("add_location_error").removeClass("hidden");
    if ($("add_location_header")) {
      $("add_location_header").addClass("error");
    } else {
      $("add_location_input").addClass("error");
      $("add_location_text").addClass("error");
    }    
  },
  
  _clearLocationError: function() {
    $("add_location_error").addClass("hidden");
    if ($("add_location")) {
      $("add_location_text").setText(map_removeaddress);
      $("add_location").addClass("hidden");
      $("add_location_header").removeClass("error");
      $('add_location_input').value = map_addresstemplate;
    } else {
      $("add_location_input").removeClass("error");
      $("add_location_text").removeClass("error");      
    }    
  },

  _addLocationCallback: function(point) {
    if (point == null) {
      ta.maps.Sidebar._setLocationError(map_addressnotfound);
      return;
    }

    var map = ta.retrieve('maps.map');
    var center = map.mapCenter();
    var dist = center.distanceFrom(point) / 1609.344;  // meter -> mile

    if (dist > 100) {
      ta.maps.Sidebar._setLocationError(map_addressnotfound2.replace('{0}', geoName));
      return;
    }

    var address = ta.retrieve('maps.address');

    ta.maps.Sidebar._clearLocationError();
    map.replaceMarkers( [{
                           lat: point.lat(),
                           lng: point.lng(),
                           customHover: {
                             title: map_myaddress,
                             contents: new Element('div').setText(address)
                               .adopt(new Element('br'))
                               .adopt(new Element('a', {'target': '_blank', 'rel': 'nofollow', 'href': map_gmaps_address_url + encodeURIComponent(address)}).setText(map_drivingdirections))
                           }
                         }],
                        'location', { anchorX: 5, anchorY: 30,
                                      pinSize: new ta.support.Size(23,28), pinOffset: 102, pinIndex: 1, hoverIndex: 2,
                                      shadowSize: new ta.support.Size(23,28), shadowOffset: 102, shadowIndex: 0,
                                      iconSize: new ta.support.Size(19,23), iconOffset: 18, iconIndex: 0,
                                      iconOffsetX: 2, iconOffsetY: 2
                                    });
    map.showType('location');

    map._move(point.lat(), point.lng(), map.getZoom());
  },

  morphBigPromo: function(event, elmt) {
    ta.store('maps.morphBigSource', 'p');
    return ta.servlet.HACSearch.morphBig(event, elmt);
  }
};

ta.servlet.BCHotelSidebarFilter = ta.servlet.HotelFilter.extend({
  initialize: function() {
    this.registerForLocationHash();
  },

  _makeHotelRestaurantAttractionClosure: function(type) {
    return function() {
      $("sidebar_" + type).checked = 1;
      var index = -1;
      if (type == "hotels") {
        index = 1;
      }
      else if (type == "attractions") {
        index = 2;
      }
      else if (type == "restaurants") {
        index = 3;
      }
      ta.maps.Sidebar._addHotelRestaurantAttraction(type.substr(0, type.length - 1), index);
    };
  },

  _makeLandmarkClosure: function(type) {
    return function() {
      $("sidebar_" + type).checked = 1;
      ta.maps.Sidebar.addLandmark(type);
    };
  },

  _makeAddressClosure: function(address) {
    return function() {
      ta.maps.Sidebar._addLocation(address);
    };
  },

  _makeAirportsClosure: function(airports) {
    return function() {
      if (!airports) return; // TODO: why are blank airports being passed in for hotels redesign?
      ta.maps.Sidebar._openAccordion($('toggle_airports'), 'airports', 'airport_');
      airports.split(",").each(function(x) {
        $('airport_' + x).checked = 1;
        ta.maps.Sidebar.togglePOI(null, $('airport_' + x));
      });
      ta.maps.Sidebar._closeAccordion($('toggle_airports'), 'airports');
    };
  },

  _makeConventionCentersClosure: function(conventionCenters) {
    return function() {
      ta.maps.Sidebar._openAccordion($('toggle_convention_centers'), 'conventionCenters', 'convention_center_');
      conventionCenters.split(",").each(function(x) {
        $('convention_center_' + x).checked = 1;
        ta.maps.Sidebar.togglePOI(null, $('convention_center_' + x));
      });
      ta.maps.Sidebar._closeAccordion($('toggle_convention_centers'), 'conventionCenters');
    };
  },

  restoreOptions: function(options) {
    this.parent(options);

    var _this = this;

    var queue = [];
    ["hotels", "restaurants", "attractions"].each(function(x) {
      if (options.hasKey("bc_" + x)) {
        queue.push(_this._makeHotelRestaurantAttractionClosure(x));
      }
    });

    ["coffee", "copy", "rail", "shipping"].each(function(x) {
      if (options.hasKey("bc_" + x)) {
        queue.push(_this._makeLandmarkClosure(x));
      }
    });

    if (options.hasKey("bc_address")) {
      var address = options.get("bc_address");
      queue.push(this._makeAddressClosure(address));;
    }

    if (options.hasKey("bc_airports")) {
      queue.push(this._makeAirportsClosure(options.get("bc_airports")));
    }
    if (options.hasKey("bc_convention_centers")) {
      queue.push(this._makeConventionCentersClosure(options.get("bc_convention_centers")));
    }

    try {
        queue.each(function(fn) { fn(); });
    } catch( ex ) {
      //ignore exception - functions will be run from the queue later
    }
    ta.store('maps.queuedSidebar', queue);
  },

  update: function() {
    var _this = this;

    ["hotels", "restaurants", "attractions", "coffee", "copy", "rail", "shipping"].each(function(x) {
      if ($("sidebar_" + x) && $("sidebar_" + x).checked) {
        _this.setOption("bc_" + x, 1);
      }
    });

    ["airports", "convention_centers"].each(function(x) {
        var type = x.substr(0, x.length - 1);
        var selector = "#" + type + "_list input";
        var elements = $$(selector);
        var open = [];
        elements.each(function(elt) {
                        if (elt.checked) {
                          var id = elt.id;
                          var idx = id.lastIndexOf("_");
                          id = id.substr(idx + 1);
                          open.push(id);
                        }
                      });
        _this.setOption("bc_" + x, open.join(","));
    });

    if (ta.has("maps.address")) {
      this.setOption("bc_address", ta.retrieve("maps.address"));
    } else {
      this.removeOption("bc_address");
    }

    this.parent();
  }
});
// overwrite the HACSearch filter on Business Center pages to add sidebar functionality
ta.servlet.HACSearch.filter = new ta.servlet.BCHotelSidebarFilter();
