// Much of this code copied from Chipotle's store finder

var map;
var geocoder;
var directions;
var directionsOptions;

var radius;
var zip1;
var zip2;

var searchCoords1;
var searchCoords2;
var gshops = [];
var latitude;
var longitude;
var zoomlevel;
var xmlRequestPage = self.location.pathname + '/storeXml';
var baseIcon;
var startMarker;
var endMarker;

/*
// Monitor the window resize event
if (window.attachEvent) { 
  window.attachEvent("onresize", function() {mapSize()} );        
} else { 
  window.addEventListener("resize", function() {mapSize()} , false);
}
*/


// Call this function when the page has been loaded
function initialize() {
  map = new GMap2(document.getElementById("storemap"));

  map.addControl(new GSmallMapControl());
  map.addControl(new GMapTypeControl());
  map.addControl(new GScaleControl());

  map.setCenter(new GLatLng(35.89, -86.34), 6);
  
  geocoder = new GClientGeocoder();
  
  directions = new GDirections(map, null);
  directionsOptions = { getSteps: true };
  GEvent.addListener(directions, "load", onGDirectionsLoad);
  GEvent.addListener(directions, "error", handleGDirectionsErrors);
  
//  Create a base icon for all of our markers that specifies the shadow, icon dimensions, etc.
  baseIcon = new GIcon();
  baseIcon.shadow = "http://www.google.com/mapfiles/shadow50.png";
  baseIcon.iconSize = new GSize(32, 32);
  baseIcon.shadowSize = new GSize(37, 34);
  baseIcon.iconAnchor = new GPoint(0, 34);
  baseIcon.infoWindowAnchor = new GPoint(16, 32);
  baseIcon.infoShadowAnchor = new GPoint(24, 20);
  
  
  baseStartEndIcon = new GIcon();
  baseStartEndIcon.shadow = "http://www.google.com/mapfiles/shadow50.png";
  baseStartEndIcon.iconSize = new GSize(24, 38);
  baseStartEndIcon.shadowSize = new GSize(37, 34);
  baseStartEndIcon.iconAnchor = new GPoint(9, 34);
  
  startMarkerIcon = new GIcon(baseStartEndIcon);
  startMarkerIcon.image = "http://maps.google.com/intl/en_us/mapfiles/icon_greenA.png";
  startMarker = new GMarker(new GLatLng(35.89, -86.34), {icon: startMarkerIcon});
  map.addOverlay(startMarker);
  startMarker.hide();

  endMarkerIcon = new GIcon(baseStartEndIcon);
  endMarkerIcon.image = "http://maps.google.com/intl/en_us/mapfiles/icon_greenB.png";
  endMarker = new GMarker(new GLatLng(36.89, -85.34), {icon: endMarkerIcon});
  map.addOverlay(endMarker);
  endMarker.hide();

  var getVars = getUrlVars();
  if (getVars['zip1']) {
    var zip = getVars['zip1'];
    $('input#storelocator_zip1_input').val(zip);
    // Set default radius to 5 miles
    $('select#storelocator_pickradius_input').val('5');
    doSearchNearZip();
  }
}


/*
 * Searches for Daily's locations by zip code and radius
 */
function doSearchNearZip() {
  // Hide the start and end markers and directions
  startMarker.hide();
  endMarker.hide();
  directions.clear();

  radius = $('select#storelocator_pickradius_input').val();
  zip1 = $('input#storelocator_zip1_input').val();
  zip2 = $('input#storelocator_zip2_input').val();

  geocoder.getLatLng(zip1,
    function(point) {
      if (!point) {
        alert("Starting point " + zip1 + " not found");
      }
      // If the second zip code is entered, geolocate the second zip code
      else if (zip2) {
        searchCoords1 = point;
        //console.log("Setting start marker point to ("+searchCoords1.lat()+", "+searchCoords1.lng()+") and showing");
        startMarker.setPoint(searchCoords1);
//        startMarker.show();
        doSearchNearZip2();
      } else {
        searchCoords1 = point;
        //console.log("Setting start marker point to ("+searchCoords1.lat()+", "+searchCoords1.lng()+") and showing");
        startMarker.setPoint(searchCoords1);
        startMarker.show();
        continueDoSearchNearZip(point);
      }
    });

  return false;
}
function doSearchNearZip2(point) {
  geocoder.getLatLng(zip2,
    function(point) {
      if (!point) {
        alert("Starting point " + zip2 + " not found");
      } else {
        searchCoords2 = point;
        //console.log("Setting end marker point to ("+searchCoords2.lat()+", "+searchCoords2.lng()+") and showing");
//        endMarker.setPoint(searchCoords2);
        endMarker.show();
        
        var fromAndTo = "from: " + zip1
                 + " to: " + zip2;
        directions.load(fromAndTo, directionsOptions);
        // The script will now go to onGDirectionsLoad
      }
    });

  return false;
}

function onGDirectionsLoad() {
  var route = directions.getPolyline();
  if(route.getVertexCount() > 4) {
    // Average the points down to only 5
    var points = new Array();
    var numPoints = 5;
    var numVertices = route.getVertexCount();
    var vertexIncrement = Math.floor(numVertices/numPoints);
    var curVertexNumber = 0;
    for(i=0; i<numPoints; i++) {
      points[i] = route.getVertex(curVertexNumber);
      curVertexNumber += vertexIncrement;
    }
    points[4] = route.getVertex(route.getVertexCount()-1);
    continueDoSearchNearZip(points);
  } else {
    alert('No route found');
  }
}


function handleGDirectionsErrors() {
  if (directions.getStatus().code == G_GEO_UNKNOWN_ADDRESS)
    alert("The starting or ending address you entered couldn't be found. Make sure you typed them both in correctly.");
  else if (directions.getStatus().code == G_GEO_SERVER_ERROR)
    alert("A geocoding or directions request could not be successfully processed, yet the exact reason for the failure is not known.\n Error code: " + gdir.getStatus().code);
     
  else if (directions.getStatus().code == G_GEO_MISSING_QUERY)
    alert("Please specify both a starting and ending address");

  else if (directions.getStatus().code == G_GEO_BAD_REQUEST)
    alert("A directions request could not be successfully parsed.");
    
  else alert("An unknown error occurred.");

}


function continueDoSearchNearZip(avgPoints) {
  var request = GXmlHttp.create();
  var xmlQueryUrl;

  if(!avgPoints) {  // If only a starting zip code was entered
    xmlQueryUrl = xmlRequestPage
            + '?radius=' + radius
            + '&lat1=' + searchCoords1.lat()
            + '&lng1=' + searchCoords1.lng()
  } else {
    xmlQueryUrl = xmlRequestPage
            + '?radius=' + radius
            + '&lat1=' + searchCoords1.lat()
            + '&lng1=' + searchCoords1.lng();
    for(i=0; i<avgPoints.length; i++) {
      xmlQueryUrl += '&lat' + (i+2) + '=' + avgPoints[i].lat()
            +  '&lng' + (i+2) + '=' + avgPoints[i].lng();
    }
  }
  request.open("GET", xmlQueryUrl, true);
  request.onreadystatechange = function() {
    if (request.readyState == 4) {
      // First clear the current markers, if any

      for (var i = 0; i < gshops.length; i++) {
        map.removeOverlay(gshops[i]);
      }
      gshops = new Array();
      
      var xmlDoc = request.responseXML;
      
      // obtain the array of markers and loop through it
      var markers = xmlDoc.documentElement.getElementsByTagName("Placemark");
//      var locationtext = xmlDoc.documentElement.getElementsByTagName("locationtext")[0].firstChild.nodeValue;
      var locationtext = zip1;
      var NumberOfStores = xmlDoc.documentElement.getElementsByTagName("NumberOfStores")[0].firstChild.nodeValue;
//      writeResults(markers.length, locationtext, NumberOfStores);
      
      var points = new Array();
      for (var i = 0; i < markers.length; i++) {
        // obtain the attribues of each marker
        var addr = markers[i].getElementsByTagName("description")[0].firstChild.nodeValue;
        var coords = markers[i].getElementsByTagName("coordinates")[0].firstChild.nodeValue.split(",");
        var lat = parseFloat(coords[0]);
        var lng = parseFloat(coords[1]);
        var point = new GLatLng(lat,lng);
        points[i] = point;
        var name = markers[i].getElementsByTagName("name")[0].firstChild.nodeValue;
        var html = "";
        // create the marker
        html = "<b><a href='javascript:mapPanAndZoomTo(" + lat + "," + lng + ")' title='zoom'>"+name+"</a></b><br />"+addr;
        var marker = createMarker(point,name,html,0,i);
        map.addOverlay(marker);
        gshops.push(marker);
        
        writeLocation(lat, lng, name, addr, i);
      }
      if (markers.length > 0) {
        fitMap(map, points);
      } else {
        // Don't move the map
        // Show an alert saying that no locations were found
        var milesPlural = "mile" + ((radius==1) ? '' : 's');
        if(zip2.length == 0) {
          alert("No Daily's locations were found within "
            + radius +" "+ milesPlural +" of " + zip1);
        } else {
          alert("No Daily's locations were found within "
            + radius +" "+ milesPlural +" along the route from '"+ zip1 +"' to '"+ zip2 +"'");
        }
      }
    }
  }
  request.send(null);
}


// Creates the marker and sets up the event window
function createMarker(point,name,html,zoom,index) {
  var letter = String.fromCharCode("A".charCodeAt(0) + index);
//  var graphic = "http://www.google.com/mapfiles/marker" + letter + ".png";
  var graphic = "/images/dailys-marker.png";
  
  var icon = new GIcon(baseIcon);
  icon.image = graphic;
  var marker = new GMarker(point, icon);
  marker.html = html;

  GEvent.addListener(marker, "click", function() {
    map.panTo(point);
    marker.openInfoWindowHtml(html);
  });
  
  return marker;
}


/*
 * Resizes and centers the map when the browser is resized
 */
function mapSize() {
  if (window.innerWidth) {
    document.getElementById("storemap").style.width = (window.innerWidth - 300) + "px";
//    document.getElementById("dailys_locations").style.height = (window.innerHeight - 135) + "px";
  } else if (document.all) {
    document.getElementById("storemap").style.width = (document.body.clientWidth - 300) + "px";
//    document.getElementById("dailys_locations").style.height = (document.body.clientHeight - 135) + "px";
  }
  
  if (map != null) {
    map.checkResize();
    map.panTo(new GLatLng(latitude, longitude));
  }
}


/*
 * Centers the map on the selected location and opens its info pannel
 */
function mapPanAndZoomTo(lat,lng) {
  if (map != null) {
    map.setZoom(16);
    map.setCenter(new GLatLng(lat, lng));
  }
}


/*
 * Fits the map to be just big enough to contain all the results
 */
function fitMap(map, points) {
  var bounds = new GLatLngBounds();
  for (var i=0; i< points.length; i++) {
    bounds.extend(points[i]);
  }
  var zoomLevel = map.getBoundsZoomLevel(bounds)
  // Don't automatically zoom in way too far
  if(zoomLevel > 13) {
    zoomLevel = 13;
  }
  map.setZoom(zoomLevel);
  map.setCenter(bounds.getCenter());
}

/*
 * Pans to the marker on the map and opens its info pannel
 */
function mapOpenInfo(index) {
  if (map != null) {
    var marker = gshops[index];
    map.panTo(marker.getPoint());
    marker.openInfoWindowHtml(marker.html);
  }
} 


/*
 * Writes the total results in the sidebar
 */
function writeResults(total, locationtext, NumberOfStores) {
  var s;
  if (total > 0) {
    s = 'Showing ' + total + /* ' of ' + NumberOfStores + */ ' locations near ' + locationtext + '';
  } else {
    s = 'No locations found near ' + locationtext;
  }
  document.getElementById("dailys_locations_results").innerHTML = '<ul>' + s + '</ul>';
}


/*
 * Writes the locations in the sidebar
 * Clicking a location centers the map
 */
function writeLocation(lat, lng, name, addr, index) {
//  var letter = String.fromCharCode("A".charCodeAt(0) + index);
//  var graphic = "http://www.google.com/mapfiles/marker" + letter + ".png";
  var graphic = "images/dailys-marker.png";
  var list = document.getElementById("dailys_locations_results");
  var s = list.innerHTML;
  s += '<li><img src="/images/shim.gif" width="200" height="1"><br /><div class="marker"><a href="javascript:mapOpenInfo(' + index + ')"><img src="' + graphic + '" border="0" /></a></div>';
  s += '<div class="address"><a href="javascript:mapOpenInfo(' + index + ')" class="storename">' + name + '</a><br />';
  s += addr + '</div>';
  s += '</li>';

  list.innerHTML = s;
}


// Read a page's GET URL variables and return them as an associative array.
function getUrlVars()
{
  var vars = [], hash;
  var hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&');

  for(var i = 0; i < hashes.length; i++)
  {
    hash = hashes[i].split('=');
    vars.push(hash[0]);
    vars[hash[0]] = hash[1];
  }

  return vars;
}
