/* a list of attributes of the cities for which we have detailed maps */
var cities = [
    {
        'id': 'boston',
        'name': 'Boston',
        'bbox': new YAHOO.util.Region(126, 760, 136, 751),
        'width': 476,
        'height': 500
    },
    {
        'id': 'chicago',
        'name': 'Chicago',
        'bbox': new YAHOO.util.Region(177, 530, 187, 523),
        'width': 326,
        'height': 500
    },
    {
        'id': 'dallas',
        'name': 'Dallas',
        'bbox': new YAHOO.util.Region(356, 401, 367, 384),
        'width': 800,
        'height':478
    },
    {
        'id': 'dc',
        'name': 'Washington, D.C.',
        'bbox': new YAHOO.util.Region(213, 690, 220, 684),
        'width': 479,
        'height': 500
    },
    {
        'id': 'denver',
        'name': 'Denver',
        'bbox': new YAHOO.util.Region(215, 284, 228, 272),
        'width': 435,
        'height': 500
    },
    {
        'id': 'detroit',
        'name': 'Detroit',
        'bbox': new YAHOO.util.Region(157, 597, 172, 582),
        'width': 484,
        'height': 500
    },
    {
        'id': 'houston',
        'name': 'Houston',
        'bbox': new YAHOO.util.Region(414, 425, 427, 412),
        'width': 507,
        'height': 500
    },
    {
        'id': 'los_angeles',
        'name': 'Los Angeles',
        'bbox': new YAHOO.util.Region(290, 75, 310, 52),
        'width': 625,
        'height': 500
    },
    {
        'id': 'miami',
        'name': 'Miami',
        'bbox': new YAHOO.util.Region(450, 688, 483, 673),
        'width': 144,
        'height': 500
    },
    {
        'id': 'minneapolis',
        'name': 'Minneapolis/St. Paul',
        'bbox': new YAHOO.util.Region(119, 454, 134, 439),
        'width': 501,
        'height': 500
    },
    {
        'id': 'new_york',
        'name': 'New York',
        'bbox': new YAHOO.util.Region(166, 729, 179, 716),
        'width': 500,
        'height': 500
    },
    {
        'id': 'philadelphia',
        'name': 'Philadelphia',
        'bbox': new YAHOO.util.Region(187, 714, 194, 706),
        'width': 583,
        'height': 500
    },
    {
        'id': 'phoenix',
        'name': 'Phoenix',
        'bbox': new YAHOO.util.Region(321, 166, 336, 147),
        'width': 744,
        'height': 500
    },
    {
        'id': 'san_diego',
        'name': 'San Diego',
        'bbox': new YAHOO.util.Region(315, 80, 332, 67),
        'width': 319,
        'height': 500
    },
    {
        'id': 'san_francisco',
        'name': 'San Francisco',
        'bbox': new YAHOO.util.Region(202, 31, 227, 11),
        'width': 333,
        'height': 500
    },
    {
        'id': 'seattle',
        'name': 'Seattle',
        'bbox': new YAHOO.util.Region(19, 78, 42, 63),
        'width': 219,
        'height': 500
    },
    {
        'id': 'tampa',
        'name': 'Tampa',
        'bbox': new YAHOO.util.Region(430, 642, 448, 629),
        'width': 315,
        'height': 500
    }
]

/* keep track of which city is currently being displayed */
var displayedCity = null;

/*
 * This is a map from city IDs -> dictionaries containing the
 * following keys:
 *
 *   - overlay:  An Overlay object that allows the city detail
 *     elements to be shown and positioned in the center of the
 *     window.
 *
 *   - detailEl:  The dynamically-created DOM element containing the
 *     city detail.  This normally has display: none and must be set
 *     to display: block before it is shown.
 */
var cityOverlayMap = {};


/* Show the overlay when the mouse enters the main image and hide it
 * when it leaves. */
function mainImageMouseOverOut(mode) {
  var value = (mode == 'over') ? 'visible' : 'hidden';
  YAHOO.util.Dom.setStyle('mainImageOverlay', 'visibility', value);
}


/* Handle mouse move events over the main image.  This changes the
 * cursor to a hand if it's over a city. */
function mainImageMouseMove(event) {
  YAHOO.util.Dom.get('mainImageOverlay').style.cursor =
      (getHoverCity(event)) ? 'pointer' : 'default';
}


/* Handle clicks on the main image.  This displays a detail overlay if
 * the mouse is hovering over a city. */
function mainImageClick(event) {

  var hoverCity = getHoverCity(event);

  /* show the detailed image for the city we're hovering over */
  if (hoverCity) {

    /* set the src attribute here (instead of createCityImageDetail())
     * to make the detail image load on demand */
    var imageEl = YAHOO.util.Dom.get('img_' + hoverCity);
    imageEl.src = 'metro_small/' + hoverCity + '.jpg';

    /* show the city detail overlay */
    YAHOO.util.Dom.setStyle(
        cityOverlayMap[hoverCity].detailEl, 'display', 'block');
    cityOverlayMap[hoverCity].overlay.show();
    YAHOO.util.Dom.setStyle('pageOverlay', 'display', 'block');

    displayedCity = hoverCity;
  }
}


/* Return the id of the city under the event, or null if the event is
 * not over a city. */
function getHoverCity(event) {

  var overlayRegion = YAHOO.util.Dom.getRegion('mainImageOverlay');
  var x = YAHOO.util.Event.getPageX(event) - overlayRegion.left;
  var y = YAHOO.util.Event.getPageY(event) - overlayRegion.top;

  for (var i = 0; i < cities.length; ++i) {
    var cityOffset = cities[i]['bbox'];
    if (cityOffset.contains(new YAHOO.util.Point(x, y))) {
      YAHOO.util.Dom.get('mainImageOverlay').style.cursor = 'pointer';
      return cities[i]['id'];
    }
  }

  if (i == cities.length) {
    return null;
  }
}


/* Programatically create a DOM tree for a city detail overlay.  This
 * returns the root of the tree, which has not yet been added to the
 * page. */
function createCityImageDetail(attribs) {

  /* create the container */
  var detailContainerEl = document.createElement('div');
  YAHOO.util.Dom.addClass(detailContainerEl, 'imageDetail');
  detailContainerEl.id = attribs['id'];

  /* add the image */
  var imageEl = document.createElement('img');
  imageEl.id = 'img_' + attribs['id'];
  imageEl.alt = attribs['name'];
  imageEl.width = attribs['width'];
  imageEl.height = attribs['height'];
  detailContainerEl.appendChild(imageEl);

  /* create the container for the links */
  var linkEl = document.createElement('div');
  YAHOO.util.Dom.addClass(linkEl, 'linkContainer');
  linkEl.appendChild(document.createTextNode(attribs['name'] + ' | '));
  detailContainerEl.appendChild(linkEl);

  /* add links to the large images */
  var largeAnchorEl = document.createElement('a');
  largeAnchorEl.href = 'metro_large/' + attribs['id'] + '.png';
  largeAnchorEl.appendChild(document.createTextNode('large'));
  linkEl.appendChild(largeAnchorEl);
  linkEl.appendChild(document.createTextNode(' | '));
  var xlargeAnchorEl = document.createElement('a');
  xlargeAnchorEl.href = 'metro_xlarge/' + attribs['id'] + '.png';
  xlargeAnchorEl.appendChild(document.createTextNode('x-large'));
  linkEl.appendChild(xlargeAnchorEl);

  return detailContainerEl;
}


/* Create a detail overlay for each city.  This also fills in
 * cityOverlayMap. */
function createCityImages() {

  var containerEl = YAHOO.util.Dom.get('detailContainer');
  for (var i = 0; i < cities.length; ++i) {

    /* create the DOM elements, append to the document, and add a
     * shadow */
    var detailEl = createCityImageDetail(cities[i]);
    containerEl.appendChild(detailEl);
    var shadowWrapper = new HAIRYCOW.ShadowedElement(detailEl);

    /* create an Overlay for the city detail */
    var overlay = new YAHOO.widget.Overlay(
        detailEl, {fixedcenter: true, visible: false, zIndex: 2});
    overlay.render();

    /* hide the city detail to prevent it from being positioned and
     * affecting the page layout */
    YAHOO.util.Dom.setStyle(detailEl, 'display', 'none');

    cityOverlayMap[cities[i].id] = {
        overlay: overlay,
        detailEl: detailEl
    }
  }
}


/* Resize the translucent page overlay so that it covers the window. */
function resizePageOverlay() {

  /* If the overlay is visible then we need to remove it before
   * setting its size.  Otherwise we may be unable to read the correct
   * document dimensions (if the window is being made smaller).
   * Remember the current value of the 'display' style so that we can
   * restore it later. */
  var oldDisplayStyle = YAHOO.util.Dom.getStyle('pageOverlay', 'display');
  YAHOO.util.Dom.setStyle('pageOverlay', 'display', 'none');

  YAHOO.util.Dom.setStyle(
      'pageOverlay', 'width', YAHOO.util.Dom.getDocumentWidth() + 'px');
  YAHOO.util.Dom.setStyle(
      'pageOverlay', 'height', YAHOO.util.Dom.getDocumentHeight() + 'px');

  YAHOO.util.Dom.setStyle('pageOverlay', 'display', oldDisplayStyle);
}


YAHOO.util.Event.onDOMReady(function() { 

  /* Fetch the main image overlay.  It's a transparent PNG so this
   * takes care of it on IE6. */
  var imageGroup = new YAHOO.util.ImageLoader.group(null, null);
  imageGroup.registerPngBgImage('mainImageOverlay', 'pop_us_overlay.png');
  imageGroup.fetch();

  /* create the city detail overlays */
  createCityImages();

  /* style the translucent overlay that dims the rest of the page when
   * a city overlay is being displayed */
  resizePageOverlay();
  YAHOO.util.Dom.setStyle('pageOverlay', 'opacity', '0.5');
  YAHOO.util.Event.addListener(window, 'resize', resizePageOverlay);

  /* add an onclick handler that dismisses the city detail overlay */
  YAHOO.util.Event.addListener('pageOverlay', 'click', function() {
    cityOverlayMap[displayedCity].overlay.hide();
    YAHOO.util.Dom.setStyle(
        cityOverlayMap[displayedCity].detailEl, 'display', 'none');
    YAHOO.util.Dom.setStyle('pageOverlay', 'display', 'none');
    displayedCity = null;
  });
});
