RandomSelection = Class.create({});

RandomSelection.addMethods(
{
  initialize: function(elements) 
  {
    this.items = elements;
  },
  hideAll: function() {
    this.items.each(function(target) { target.hide() });
  },
  showRandom: function() {
    this.hideAll();

    var index = Math.floor(Math.random()*this.items.size())
    if (this.items[index] != null)
    {
      this.items[index].show();
    }
  }
});
OfficeSearchModel = Class.create({})

Object.extend(OfficeSearchModel, 
{
  ZIP_CODE_SEARCH: 0,
  TERRITORY_SEARCH: 1
});

OfficeSearchModel.addMethods(
{
  initialize: function(post_code, distance, region, country, city) {
    this.post_code = post_code;
    this.distance = distance;
    this.region = region;
    this.country = country;
    this.city = city;
    this.go_action = '';
    this.country_cache = {};
    this.city_cache = {};
  },
  getSearchUrl: function(value) {
    var prefix = '';
    if (window.location.pathname.match(/\/amexnetwork/) != null) {
      prefix = '/amexnetwork';
    }
    if (this.go_action == OfficeSearchModel.ZIP_CODE_SEARCH) {
      return prefix + '/offices/?post_code=' + this.post_code + '&radius=' + this.distance + "#/1/" + this.selected_services();
    }
    if (this.go_action == OfficeSearchModel.TERRITORY_SEARCH) {
      if (this.isRegionAState()) {
        return prefix + '/offices/?region=' + this.region + '&state=' + this.country + '&city=' + this.city + "#/1/" + this.selected_services();
      }
      else {
        return prefix + '/offices/?region=' + this.region + '&country=' + this.country + '&city=' + this.city + "#/1/" + this.selected_services();
      }
    }
    return null;
  },
  selected_services: function()
  {
    var str = '';
    var selected = [];
    $$(OfficeSearchController.SERVICES).each(function(target) {
      if (target.checked) selected.push(target.value);
    });
    str = '[' + selected.join(',') + ']';
    return str;
  },
  hasCountry: function() 
  {
    return (this.country != '');
  },
  hasRegion: function() 
  {
    return (this.region != '');
  },
  isCanada: function()
  {
    return (this.region == 'CAN');
  },
  isUSA: function()
  {
    return (this.region == 'USA');
  },
  isRegionAState: function()
  {
    return (this.isCanada() || this.isUSA());
  },
  loadCountries: function(callback)
  {
    if (this.country_cache[this.region] == null) {
      var url = '/countries/' + this.region;
      new Ajax.Request(url, 
      { 
        method: 'get', 
        onSuccess: function(transport) {
          callback(transport.responseText);
          this.country_cache[this.region] = transport.responseText;
        }.bind(this)
      });
    }
    else {
      callback(this.country_cache[this.region]);
    }
  },
  loadCities: function(callback)
  {
    if (this.city_cache[this.region + this.country] == null) {
      var url = '/cities/' + this.region + '/' + this.country;
      new Ajax.Request(url, 
      { 
        method: 'get', 
        onSuccess: function(transport) {
          callback(transport.responseText);
          this.city_cache[this.region + this.country] = transport.responseText;
        }.bind(this)
      });
    }
    else {
      callback(this.city_cache[this.region + this.country]);
    }
  },
  resetTerritorySearch: function(value) 
  {
    this.region = '';
    this.country = '';
    this.city = '';
  },
  resetZipCodeSearch: function(value) 
  {
    this.post_code = '';
    this.distance = '50';
  },
  setPostCode: function(value) {
    this.post_code = value;
    this.go_action = OfficeSearchModel.ZIP_CODE_SEARCH;
  },
  setDistance: function(value) {
    this.distance = value;
    this.go_action = OfficeSearchModel.ZIP_CODE_SEARCH;
  },
  setRegion: function(value) {
    this.region = value;
    this.go_action = OfficeSearchModel.TERRITORY_SEARCH;
  },
  setCountry: function(value) {
    this.country = value;
    this.go_action = OfficeSearchModel.TERRITORY_SEARCH;
  },
  setCity: function(value) {
    this.city = value;
    this.go_action = OfficeSearchModel.TERRITORY_SEARCH;
  }
});

OfficeSearchController = Class.create({});

Object.extend(OfficeSearchController, 
{
	FILTER_MENU: '#MGLNResults #MGLNResults-FilterByServices',
	FILTER_MENU_HELP: '#MGLNResults #MGLNResults-FilterByServices a.help',
	FILTER_DISPLAY_TOGGLE: '#MGLNResults #MGLNResults-FilterByServices a.toggle',
	FILTER_OPTION_FIELDSET: '#MGLNResults #MGLNResults-FilterByServices #MGLNResults-OptionFields',
  	ZIP_FIELDSET: 'zip_fields',
    ZIP_CODE_TEXT: '.zipcode_text',
    DISTANCE_SELECT: '.distance_select',
	TERRITORY_FIELDSET: 'territory_fields',
	  REGION_SELECT: '.region_select',
	  COUNTRY_SELECT: '.country_select',
	  CITY_SELECT: '.city_select',
	  COUNTRY_LABEL: '.country_label',
	SERVICES: '.service_input',
	GO_BUTTON: '#go_button',
	STRINGS: {
		FILTER_MENU_TOGGLE_HIDDEN: "Filter by Travel Office Services",
		FILTER_MENU_TOGGLE_SHOWN: "All Services Offered",
		FILTER_MENU_HELP_HIDDEN: "&nbsp;",
		FILTER_MENU_HELP_SHOWN: "What are these services?"
	}
});

OfficeSearchController.addMethods(
{
	initialize: function() 
	{
		try {
      this.model = new OfficeSearchModel('', '50', '', '', '');
       
      $$(OfficeSearchController.FILTER_DISPLAY_TOGGLE).invoke('observe', 'click', this.handleFilterMenuToggle.bindAsEventListener(this));
      $$(OfficeSearchController.ZIP_CODE_TEXT).invoke('observe', 'click', this.handleClickZipText.bindAsEventListener(this));
      $$(OfficeSearchController.ZIP_CODE_TEXT).invoke('observe', 'change', this.handleChangeZipText.bindAsEventListener(this));
      $$(OfficeSearchController.ZIP_CODE_TEXT).invoke('observe', 'keypress', this.handleKeyPressZipText.bindAsEventListener(this));
      $$(OfficeSearchController.DISTANCE_SELECT).invoke('observe', 'change', this.handleSelectDistance.bindAsEventListener(this));
       
      $$(OfficeSearchController.REGION_SELECT).invoke('observe', 'change', this.handleSelectRegion.bindAsEventListener(this));
      $$(OfficeSearchController.COUNTRY_SELECT).invoke('observe', 'change', this.handleSelectCountry.bindAsEventListener(this));
      $$(OfficeSearchController.CITY_SELECT).invoke('observe', 'change', this.handleSelectCity.bindAsEventListener(this));
       
      $$(OfficeSearchController.GO_BUTTON).invoke('observe', 'click', this.handleClickGo.bindAsEventListener(this));
            
      this.resetTerritorySearch();
      this.resetZipCodeSearch();
		}
    catch (error) 
    {
      Logger.log("WARING: initialize failed: " + error);
    }
	},
	handleFilterMenuToggle: function (event)
	{
		var menu = $$(OfficeSearchController.FILTER_MENU).first();
		var fieldset = $$(OfficeSearchController.FILTER_OPTION_FIELDSET).first();
		if (menu != null && fieldset != null)
		{
			if (menu.hasClassName('open'))
			{
				menu.removeClassName('open');
				menu.addClassName('closed');
				
				event.target.removeClassName('open');
				event.target.addClassName('closed');
				event.target.innerHTML = OfficeSearchController.STRINGS.FILTER_MENU_TOGGLE_HIDDEN;
				
				$$(OfficeSearchController.FILTER_MENU_HELP).first().innerHTML = OfficeSearchController.STRINGS.FILTER_MENU_HELP_HIDDEN;
				
				fieldset.hide();
			}
			else
			{
				menu.removeClassName('closed');
				menu.addClassName('open');
				
				event.target.removeClassName('closed');
				event.target.addClassName('open');
				event.target.innerHTML = OfficeSearchController.STRINGS.FILTER_MENU_TOGGLE_SHOWN;
				
				$$(OfficeSearchController.FILTER_MENU_HELP).first().innerHTML = OfficeSearchController.STRINGS.FILTER_MENU_HELP_SHOWN;
				
				fieldset.show();
			}
		}
	},
	handleClickZipText: function(event)
	{
	  try {
	    this.switchToZipCodeSearch();
	    if (event.target.value == '') {
	      event.target.value = '';
	    }
    }
    catch (error) {
      Logger.log("WARING: handleClickZipText failed: " + error);
    }
	},
	handleChangeZipText: function(event)
	{
	  try {
	    this.switchToZipCodeSearch();
	    this.model.setPostCode(event.target.value);
    }
    catch (error) {
      Logger.log("WARING: handleChangeZipText failed: " + error);
    }
	},
	handleKeyPressZipText: function(event)
	{
	  try {
	    this.switchToZipCodeSearch();
	    
	    var zipCode = event.target.value;
	    if (zipCode.length > 4) {
	      zipCode = zipCode.substring(0, 5);
        event.target.value = zipCode;
	    }
	    this.model.setPostCode(zipCode);

	    var key = event.charCode || event.keyCode;
	    if (key == 13 || key == 0){ // enter keys
    	  Event.stop(event);
	      this.handleClickGo(event);
      }
	  }
	  catch (error) {
      Logger.log("WARING: handleKeyPressZipText failed: " + error);
	  }
	},
	handleSelectDistance: function(event)
	{
	  try {
	    this.switchToZipCodeSearch();
	    this.model.setDistance(event.target.value);
    }
    catch (error) {
      Logger.log("WARING: handleSelectDistance failed: " + error);
    }
	},
	handleSelectRegion: function(event)
	{
	  try {
	    this.switchToTerritorySearch();
	    this.model.setRegion(event.target.value);
	    this.updateSelectCountry();
	    this.updateCountryLabel();
    }
    catch (error) {
      Logger.log("WARING: handleSelectRegion failed: " + error);
    }
	},
	handleSelectCountry: function(event)
	{
	  try {
  	  this.switchToTerritorySearch();
  	  this.model.setCountry(event.target.value);
  	  this.updateSelectCity();
    }
    catch (error) {
      Logger.log("WARING: handleSelectCountry failed: " + error);
    }
	},
	handleSelectCity: function(event) {
	  try {
  	  this.switchToTerritorySearch();
  	  this.model.setCity(event.target.value);
    }
    catch (error) {
      Logger.log("WARING: handleSelectCity failed: " + error);
    }
	},
  handleClickGo: function(event)
  {
    try {
      var url = this.model.getSearchUrl();
      if (url != null) {
        document.location = url;
      }
    }
    catch (error) {
      Logger.log("WARING: handleClickGo failed: " + error);
    }
  },
	highlighTerritorySearch: function()
	{
	  $(OfficeSearchController.TERRITORY_FIELDSET).addClassName('highlighted');
	  $(OfficeSearchController.ZIP_FIELDSET).removeClassName('highlighted');
	},
	highlightZipCodeSearch: function()
	{
	  $(OfficeSearchController.ZIP_FIELDSET).addClassName('highlighted');
	  $(OfficeSearchController.TERRITORY_FIELDSET).removeClassName('highlighted');
	},
	resetTerritorySearch: function()
	{
	  this.model.resetTerritorySearch();
	  $A($(OfficeSearchController.TERRITORY_FIELDSET).getElementsByTagName('select')).each(function(target) { target.selectedIndex = 0});
		this.updateSelectCountry();
		this.updateSelectCity();
	},
	resetZipCodeSearch: function() 
	{
	  this.model.resetZipCodeSearch();
		$$(OfficeSearchController.ZIP_CODE_TEXT).each(function(target) { target.value = ''});
	},
	focusZipCodeSearch: function()
	{
	  try {
	    $$(OfficeSearchController.ZIP_CODE_TEXT)[0].focus();
	  }
    catch (error) 
    {
      // We may not be able to focus in it if its containing blind is not visible.
    }
	},
	switchToTerritorySearch: function() 
	{
	  this.highlighTerritorySearch();
	  this.resetZipCodeSearch();
	},
	switchToZipCodeSearch: function() 
	{
	  this.highlightZipCodeSearch();
	  this.resetTerritorySearch();
	},
	updateSelectCountry: function() 
	{
	  if (this.model.hasRegion()) {
	    this.model.loadCountries(function(responseText) {
    	  $$(OfficeSearchController.COUNTRY_SELECT).each(function(target) { 
    	    target.update(responseText);
    	    target.enable();
    	  });
	    });
	  }
	  else {
  	  $$(OfficeSearchController.COUNTRY_SELECT).each(function(target) { target.disable() });
	  }
	},
	updateCountryLabel: function()
	{
	  var label = "Country";
	  if (this.model.isCanada()) {
	    label = "Province";
	  }
	  if (this.model.isUSA()) {
	  	label = "State";
	  }
    $$(OfficeSearchController.COUNTRY_LABEL).each(function(target) { target.innerHTML = label; });
	},
	updateSelectCity: function() 
	{
	  if (this.model.hasCountry()) {
	    this.model.loadCities(function(responseText) {
    	  $$(OfficeSearchController.CITY_SELECT).each(function(target) { 
    	    target.update(responseText);
    	    target.enable();
    	  });
	    });
	  }
	  else {
  	  $$(OfficeSearchController.CITY_SELECT).each(function(target) { target.disable() });
	  }
	}
});
var LandingPageController = function() {
    var accordionMenu = new AccordionMenu($$('#SearchAccordionNav ul.blinds')[0]);

    var destinations = new InteractiveDestinations($("InteractiveDestinations"));

    var servicesPopup = new PopupWindow($('service_help'));
    
    var interestsMenu = new InterestsMenu($("FindByInterest"))
}

var AccordionMenu = function(menuEl) {
    var menuEl = menuEl;
    var menuItems = menuEl.childElements(); // .detect(function(el) { return el.tagName.toLowerCase() == "li" });
    var availableMenuOptions = []; /* generated from the HTML -- a list of valid panel names */
    
    this.onItemClick = function(event) {
            
      // when clicking on an anchor event.target is a String and up() is not defined in IE
      if (!event.target.up) {
        return;
      }

      var li = event.target.up('li');

      if (menuItems.include(li))
      {
    		if (!li.hasClassName('open'))
    		{

          event.stop();

    			SWFAddress.setValue(li.className);

          // tell any open tooltips to close
        	document.fire('tooltip:close');
    		}
    	}

    };

    this.setBackground = function(item, isOpen) {
        var title = item.select('div.title')[0];
        var path = title.getStyle('backgroundImage');

        path = isOpen? 
            path.replace('-closed.gif', '-open.gif') :
            path.replace('-open.gif',   '-closed.gif');

        title.setStyle({ backgroundImage: path });
    };
    
    /* primary function for selection (called by selectByPath and selectByClassName) */
    this.select = function(selection) {
        menuItems.each((function(item) {
            if (item == selection) {
                item.addClassName('open');
                this.setBackground(item, true);                
            } else {
                item.removeClassName('open');
                this.setBackground(item, false);                
            }
        }).bind(this));
        this.updateFooter(selection);
    };

	this.addressChange = function (event) {    
	  this.selectByPath( event.value );
	};
	
	this.selectByPath = function(path) {
	  var selectionClassName = this.pathAsClassName(path); /* e.g.: "specialist-by-interest" */
    if (selectionClassName && availableMenuOptions.include(selectionClassName)) {
      this.selectByClassName(selectionClassName);
    } else {
  	  this.select( menuItems[0] ); /* default */
    }
	};
	
	this.getSelection = function() {
	  return menuItems.detect(function(el){ return el.hasClassName('open') })[0];
	}
	
	this.selectByClassName = function(className) {
    for (var i = 0; i < menuItems.length; i++) {
      var item = menuItems[i];
      if (item.hasClassName(className)) {
        return this.select(item);
      };
    }	  
	};
	
	this.updateFooter = function(selection) {

	  var classes = $w(selection.className);

	  if (classes.include("travel-office")) {
	    
	    AMEXFooter.toggleByName('offices');
	    
	  } else if (classes.grep(/^specialist-by-/)) {
	    
	    AMEXFooter.toggleByName('specialists');
	    
	  }
	  
	}
	
	this.pathAsClassName = function(path) {	  
	  return path.replace('/', ''); /* e.g.: "/travel-office" becomes "travel-office" */
	};

  this.initialize = function() {
  	SWFAddress.addEventListener(SWFAddressEvent.CHANGE, this.addressChange.bind(this));

    /* whitelist, to avoid scenarios where a bad # property prevents a panel from displaying */
    availableMenuOptions = menuItems.collect(function(item) { return item.className });

    /* don't Wait for SWFAddress to fire addressChange. manually update the selection (or set default) */
    /* "getPath" actually returns the URI fragment following the hash (see RFC 3986) */
    this.selectByPath(SWFAddress.getPath());

  	menuItems.invoke('observe', 'click', this.onItemClick.bind(this));      
  }
  
  this.initialize();  
};

var InteractiveDestinations = Class.create({
  container:null,
  instructions:null,
  leftmap:null,
  sidebar:null,
  selection:null,
  listings:null,
  initialize: function(container) {
    this.container = container;
    this.leftmap = this.container.select('#InteractiveDestinations-Map')[0]; /* because "map" is a reserved word */
    this.sidebar = this.container.select('#InteractiveDestinations-Sidebar')[0];
    this.instructions = this.container.select('#InteractiveDestinations-Sidebar-Instructions')[0];

    this.listings = this.sidebar.select(".listing");

    this.leftmap.observe('click', this.onMapClick.bindAsEventListener(this));    
    
    this.instructions.show();
  },
  onMapClick: function(event) {
    event.stop();
    var r, region;
    if ((r = event.target.id.match(/MapRegion-(.*)/)) && (region = r[1])) {      
      this.setSelection(region);
    }
  },
  setSelection: function(selection) {
    this.selection = selection;

    this.instructions.hide();    

    var listing = this.listings.detect(function(el){ return el.hasClassName('listing-' + selection) });
    
    var i = this.listings.length;
    while(i--) {
      this.listings[i].setStyle({display:'none'});
    }
    listing.setStyle({display:'block'})
  }
});

var InterestsMenu = Class.create({
  container:null,
  instructions:null,
  selection:null,
  tabs:null,
  tab_for_trigger: {},
  trigger_container: null,
  initialize: function(container) {
    this.container = container;
    this.instructions = this.container.select('#FindByInterest-Results p.instructions')[0];
    this.trigger_container = this.container.select('#FindByInterest-Categories')[0];

    this.triggers = this.trigger_container.select('a');
    this.tabs = this.container.select('.tab');

    this.setSelection(null);
    this.triggers.invoke('observe', 'click', this.onTriggerClick.bindAsEventListener(this));
  },
  tab_for_trigger: function(trigger) {
    if (trigger === this.triggers[0]) return this.tabs[0];
    if (trigger === this.triggers[1]) return this.tabs[1];
    if (trigger === this.triggers[2]) return this.tabs[2];
  },
  trigger_for_tab: function(tab) {
    if (tab === this.tabs[0]) return this.triggers[0].up('li');
    if (tab === this.tabs[1]) return this.triggers[1].up('li');
    if (tab === this.tabs[2]) return this.triggers[2].up('li');
  },
  removeOmniture: function() {
    /* override omniture tracking */
    this.triggers[0].setAttribute('onclick', '');
    this.triggers[1].setAttribute('onclick', '');
    this.triggers[2].setAttribute('onclick', '');    
  },
  onTriggerClick: function(event) {
    event.stop();
    event.target.blur(); /* to avoid outlines in IE6 */
    this.setSelection(this.tab_for_trigger(event.target));
  },
  setSelection: function(selection) {
    this.selection = selection;
    if (this.selection == null && !this.trigger_container.hasClassName('selected')) {
      this.instructions.show();
      this.trigger_container.removeClassName('selected');
    } else {
      this.instructions.hide();      
      this.trigger_container.addClassName('selected');

      this.triggers.map(function(t){return t.up('li')}).invoke('removeClassName', 'selected');
      this.trigger_for_tab(this.selection).addClassName('selected');
      
      this.tabs.invoke('removeClassName', 'selected');
      this.selection.addClassName('selected');
      
      this.selection.scrollTop = 0;
    }
  }
});

