

if (!this.APPION) {
    APPION = {};
}
APPION.mapControl = {};
(function () {
   var cityCount = {};
   var map;
   var request;
   var stores = [];

   // Store some of the html elements as variables
   var cityInput = document.getElementById("cityFilters");
   var mapDiv = document.getElementById("map");
   var storeInput = document.getElementById("storeList");
   var statusDisplay = document.getElementById("loadbar");

   // Add events to the form elements
   APPION.utils.addEvent(cityInput, "mousedown", function(){ showFilterLoadMsg(); });
   APPION.utils.addEvent(cityInput, "change", function(){ onFilterCity(); });

   /*----------------------------------------------------------------------
    * Hides a specified marker on the map.
    *----------------------------------------------------------------------*/
   function hideMarker(i, entry) {
     stores[i].visible = false;
     map.removeOverlay(stores[i].marker);
     entry.style.display = "none";
   }

   /*----------------------------------------------------------------------
    * Callback function creator for the Google map markers.
    *----------------------------------------------------------------------*/
   function infoCaller(i) {
     return function() { APPION.mapControl.showStore(i); };
   }

   /*----------------------------------------------------------------------
    * Callback functions for the city filter combobox.
    *----------------------------------------------------------------------*/
   function onFilterCity() {
     var city = cityInput.value;

     for (var i=0; i<stores.length; i++) {
       var entry = document.getElementById("entry" + i);
       if (city === '' || stores[i].city === city) {
	 if (!stores[i].visible) {
	   showMarker(i, entry);
	 }
       } else {
	 hideMarker(i, entry);
       }
     }
     APPION.mapControl.moveMap(stateLon,stateLat,stateZoom);

     var msg = (city === "" ? "All locations loaded!" : city + " filter loaded!");
     statusDisplay.innerHTML = msg;
   }

   /*----------------------------------------------------------------------
    * Parse the XML data when loaded by the AJAX request.
    *----------------------------------------------------------------------*/
   function parseData() {
    if (request.readyState != 4)
     {
       return;
     }

     var markers = request.responseXML.getElementsByTagName("marker");
     for (var i=0; i<markers.length; ++i) {
       // Get Store Information.
       var m = markers[i];
       var s = {name : m.getAttribute("title"),
		add1 : m.getAttribute("add1"),
		add2 : m.getAttribute("add2"),
		add3 : m.getAttribute("add3"),
		city : m.getAttribute("tags"),
		phone : m.getAttribute("phone"),
		lng : m.getAttribute("lng"),
		lat : m.getAttribute("lat")
	       };
       s.destAddr = s.add1 + ',' + s.add2;
       s.htmlAddr = s.add1 + "<br />" + s.add2 + "<br />";
       if (s.add3) {
	 s.destAddr += ',' + s.add3;
	 s.htmlAddr += s.add3 + "<br />";
       }
       stores[i] = s;

       // Keep track of the cities for the dropdown filter.
       if (!cityCount[s.city]) {
	 cityCount[s.city] = 1;
       } else {
	 cityCount[s.city] += 1;
       }

       // Create listings for the store selection list.
       var entry = document.createElement("div");
       entry.setAttribute("id", "entry" + i);
       entry.setAttribute("style", "border-bottom:1px dashed #cecece;");
       var html = '<a href="javascript:APPION.mapControl.showStore(' + i + ');">' +
	 '<b>' + s.name + '</b></a><br />' + s.htmlAddr + s.phone;

       entry.innerHTML = html;
       storeInput.appendChild(entry);

       // Add map marker.
       s.marker = new GMarker(new GLatLng(s.lat, s.lng));
       GEvent.addListener(s.marker, "click", infoCaller(i));
       showMarker(i, entry);
     }

     populateCityFilter();
     statusDisplay.innerHTML = "Location information loaded!";
   }

   /*----------------------------------------------------------------------
    * Populates the dropdown box for filtering by city name.
    *----------------------------------------------------------------------*/
   function populateCityFilter() {
     // Sort the cities.
     var cities = [];
     for (c in cityCount) {
       if (cityCount.hasOwnProperty(c)) {
	 cities.push(c);
       }
     }
     cities.sort();

     // Insert the cities as options into the filter select input.
     cityInput.options[0] = new Option("--ALL-- (" + stores.length + ")", "");
     for (var j=0; j<cities.length; j++) {
       var text = cities[j] + " (" + unescape(cityCount[cities[j]]) + ")";
       cityInput.options[j+1] = new Option(text, cities[j]);
     }
   }

   /*----------------------------------------------------------------------
    * OnMouseDown callback for filter select element.
    *----------------------------------------------------------------------*/
   function showFilterLoadMsg() {
     statusDisplay.innerHTML = "Filter may take a few moments to load...";
   }

   /*----------------------------------------------------------------------
    * Shows a specified marker on the map.
    *----------------------------------------------------------------------*/
   function showMarker(i, entry) {
     stores[i].visible = true;
     map.addOverlay(stores[i].marker);
     entry.style.display = "";
   }

   /*----------------------------------------------------------------------
    * Draw map with data.
    *----------------------------------------------------------------------*/
   APPION.mapControl.drawMap = function() {
     map = new GMap2(mapDiv);

     // Add controls to map.
     map.addControl(new GSmallMapControl());
     map.addControl(new GScaleControl());

     // Set default map center, zoom, and map type.
     map.setCenter(new GLatLng(stateLat, stateLon), stateZoom, G_NORMAL_MAP);
     map.enableScrollWheelZoom();

     // Load the XML data.
     statusDisplay.innerHTML = "Please wait while your browser loads the data...";
     request = GXmlHttp.create();
     request.open("GET", "xml/" + xmlFileName, true);
     request.onreadystatechange = parseData;
     request.send(null);
   };

   /*----------------------------------------------------------------------
    * Close info window and center on the marker location.
    *----------------------------------------------------------------------*/
   APPION.mapControl.moveMap = function(lon, lat, zoom) {
     map.closeInfoWindow();
     map.setCenter(new GLatLng(lat, lon), zoom);
   };

   /*----------------------------------------------------------------------
    * Event handler callback for map marker.
    * This zooms in to the selected store on the map and shows the
    * info window for that store.
    *----------------------------------------------------------------------*/
   APPION.mapControl.showStore = function(i) {
     var s = stores[i];

     // Combine location information for the InfoWindow,
     // and include the click-on-address Close & Center feature.
     var html = '<div onclick="APPION.mapControl.moveMap(' + s.lng + ',' + s.lat + ',14)"><b>' +
       s.name + '</b><br />' + s.htmlAddr + s.phone + '<br /></div>';

     // Add The 'get directions to here' html. It contains a form, as well as the "Close & Center" link.
     html += '<form action="http://maps.google.com/maps" method="get">' +
       '<label for="saddr"><span class="tiny">ex.:&nbsp;&quot;1 Main St, Denver, CO 80220&quot;</span>' +
       '</label><br><input type="text" size=35 maxlength=85 name="saddr" id="saddr" value="" />' +
       '<br /><input id="submit" type="submit" value="Get Driving Directions" />&nbsp;&nbsp;' +
       '<a class="tiny" href="javascript:APPION.mapControl.moveMap('+s.lng+','+s.lat+',14);">Close &amp; Center</a>' +
       '<input type="hidden" name="daddr" value="'+s.destAddr+'" />' +
       '<input type="hidden" name="hl" value="en" /></form>';

     map.setZoom(14);
     stores[i].marker.openInfoWindowHtml(html);
   };

 })();
