
//NOTE includers of this file must also include cookie.js


// ---------------- map global variables --------------------------

var MAP_WIDTH = 575;
var MAP_HEIGHT = 575;
var MM_WIDTH = 230;
var MM_HEIGHT = 200;
var DEFAULT_MAP_LAYERS = "%2BCONSTRUCTION%2BANNOTATIONS%2BCONGESTION%2BINCIDENTS%2BTRAVELTIMES%2BAIRPORTS%2BMESSAGES%2BCAMERAS%2BSPECIALEVENTS%2BHIGHLIGHTS";
var RELOAD_INTERVAL = 1000 * 60;
// should match levels in config/gui/map/ZoomManager.xml (reread below just in case)
var ZOOM_LEVELS = [0.001,0.002,0.004,0.008,0.016,0.032,0.064,0.128,0.256,0.512,1.024];
var MAP_VERSION = "V2";

//--- global variables to maintain drag state during pan ---
var panning = false;
// the starting point relative to the document (for moving the map image)
var docStartX;
var docStartY;
// the original starting point of drag, relative to document, not reset after redraws
var originX;
var originY;

// the current map state, set in setMainMap, global for event handlers; fields are the current zoomLevel, x, and y parameters
// for map?type=image and a map object for name, constants and defaults
var currentMap = new Object();

// map objects: properties are map/cookie name and default map parameters
var home = {
  name: "Home",
  zoomLevel: 3,
  mmzoomLevel: 0,
  mmx: 335800,
  mmy: 612779,
  x: 335800,
  y: 576841
};
var corridor = {
  name: "Corridor",
  zoomLevel: 3,
  mmzoomLevel: 0,
  mmx: 335800,
  mmy: 612779,
  x: 335800,
  y: 576841
};
var chicagoArea = {
  name: "Chicago Area",
  zoomLevel: 3,
  mmzoomLevel: 1,
  mmx: 335800,
  mmy: 577841,
  x: 335800,
  y: 577841
};
var chicagoCity = {
    name: "City of Chicago",
    zoomLevel: 4,
    mmzoomLevel: 2,
    mmx: 349361,
    mmy: 572965,
    x: 349361,
    y: 572965
  };
var gary = {
  name: "Gary",
  zoomLevel: 3,
  mmzoomLevel: 1,
  mmx: 393849,
  mmy: 531176,
  x: 393849,
  y: 531176
};
var milwaukee = {
  name: "Milwaukee",
  zoomLevel: 4,
  mmzoomLevel: 2,
  mmx: 326575,
  mmy: 701695,
  x: 326575,
  y: 701695
};
var rockford = {
  name: "Rockford",
  zoomLevel: 4,
  mmzoomLevel: 2,
  mmx: 241463,
  mmy: 626255,
  x: 241463,
  y: 626255
};
var madison = {
  name: "Madison",
  zoomLevel: 4,
  mmzoomLevel: 2,
  mmx: 214509,
  mmy: 716101,
  x: 214509,
  y: 716101
};
var quadcities = {
  name: "Quad Cities",
  zoomLevel: 4,
  mmzoomLevel: 2,
  mmx: 114665,
  mmy: 537250,
  x: 114665,
  y: 537250
};
var michigan = {
  name: "SW Michigan",
  zoomLevel: 2,
  mmzoomLevel: 0,
  mmx: 525049,
  mmy: 619966,
  x: 525049,
  y: 619966
};
// map cookie expiration date: 90 days from today
var MAP_COOKIE_EXPIRES = new Date();
MAP_COOKIE_EXPIRES.setTime(MAP_COOKIE_EXPIRES.getTime() + (60 * 60 * 24 * 90 * 1000));

// layer objects, visible is the current state of each (Roads, Lakes, and Counties are always on)
var construction = {
  visible: true,
  name: "Construction",
  minimumZoom: 0
}
var annotations = {
  visible: true,
  name: "Annotations",
  minimumZoom: 0
}
var congestion = {
  visible: true,
  name: "Congestion",
  minimumZoom: 0
}
var incidents = {
  visible: true,
  name: "Incidents",
  minimumZoom: 0
}
var travelTimes = {
  visible: true,
  name: "TravelTimes",
  minimumZoom: 0
}
var airports = {
  visible: true,
  name: "Airports",
  minimumZoom: 0
}
var messageSigns = {
  visible: true,
  name: "Messages",
  minimumZoom: 0
}
var cameras = {
  visible: true,
  name: "Cameras",
  minimumZoom: 0
}
var specialEvents = {
  visible: true,
  name: "SpecialEvents",
  minimumZoom: 0
}
LAYERS = [construction, annotations, congestion, incidents, travelTimes, airports, messageSigns, cameras, specialEvents];


// Read map data from server (ZOOM_LEVELS and LAYERS[i].minimumZoom)
//IESUXTAG IE6 doesn't support XMLHttpRequest so it gets the ZOOM_LEVELS in this file
var mapInformation;
var http_request = new XMLHttpRequest();
http_request.open("GET", "mapInformation", true);
http_request.send(null);
http_request.onreadystatechange = function () {
  if (http_request.readyState == 4) {
    if (http_request.status == 200) {
      mapInformation = eval("(" + http_request.responseText + ")" );
      ZOOM_LEVELS = mapInformation.zoomLevel;
      for (var i = 0;  i < LAYERS.length;  i++) {
        var layerInfo = layerWithName(LAYERS[i].name);
        if (layerInfo != null) {
          LAYERS[i].minimumZoom = layerInfo.minimumZoom;
        }
      }
    }
    else {
      alert("There was a problem loading the map information");
    }
    http_request = null;
  }
};

// Find downloaded information for layer with the given name
function layerWithName(name) {
  for (var i = 0;  i < mapInformation.layerGroup.length;  i++) {
   	for (var j = 0;  j < mapInformation.layerGroup[i].layer.length;  j++) {
	    if (mapInformation.layerGroup[i].layer[j].name == name) {
	      return mapInformation.layerGroup[i].layer[j];
	    }
    }
  }
  return null;
}

// ---------------------- main map functions ------------------------

// writes the MyMap message if there is no "Home" cookie
function writeMyMapMessage(map) {
  if (map.name == "Home" && getCookieValue("Home" + MAP_VERSION) == null) {
    document.writeln("<div id='myMapMessage' style='padding: 0px 10px 0px 0px'>\n"
      + "<p>Welcome to the GCM Travel web site.  The home page displays a map that you can scroll or zoom to "
      + "your area of interest.  When you return to the site or select \"My Map\" from the \"Maps\" menu, the map "
      + "will display that area.  (This information is saved in a cookie on your browser.)  Whether each map layer is "
      + "visible is also saved.</p>");
    document.writeln("</div>");
  }  
}

// set MAP_WIDTH and MAP_HEIGHT based on the window size
function setMapDimensions() {
	if (typeof(window.innerWidth) == 'number') {
		// standards (w3c) complaint browser
		MAP_WIDTH = window.innerWidth - 240 - 35;
		MAP_HEIGHT = window.innerHeight - 125 - 10;
	}
	else if (document.documentElement
	    && (document.documentElement.clientWidth || document.documentElement.clientHeight)) {
		// internet explorer (something is different about the margins on IE ...)
		MAP_WIDTH = document.documentElement.clientWidth - 240 - 20;
		MAP_HEIGHT = document.documentElement.clientHeight - 125 - 10;
	}
	else {
		MAP_WIDTH = 575;
		MAP_HEIGHT = 575;
	}
	if (MAP_WIDTH < 600) {
	  MAP_WIDTH = 600;
	}
	if (MAP_HEIGHT < 545) {
	  MAP_HEIGHT = 545;
	}
  // mapViewport isn't there on the first call during page layout
  if (document.getElementById("mapViewport")) {
    document.getElementById("mapViewport").width = MAP_WIDTH;
    document.getElementById("mapViewport").height = MAP_HEIGHT;
  }
  window.onresize = resizeMap;
}

function resizeMap(e) {
	setMapDimensions();
	setMainMap(currentMap.map);
}

// sets currentMap fields from map (possibly overridden from the map cookie), sets LAYERS[].visible
// from the mapLayers cookie, sets the "mainmap" src URL (loadMainMap), and register event handlers
// x & y are passed in as request parameters to map.jsp
function setMainMap(map, eventId) {
  currentMap.map = map;
  // for MyMap only: set currentMap.zoomLevel, x, and y from the cookie if any;
  // otherwise set them from the argument map
  var params =  getCookieValue(currentMap.map.name + MAP_VERSION);
  if (params != null) {
    var start = params.indexOf("zoomLevel:") + 10;
    var end = params.indexOf("|", start);
    currentMap.zoomLevel = params.substring(start, end);
    start = params.indexOf("x:") + 2;
    end = params.indexOf("|",start);
    currentMap.x = params.substring(start,end);
    start = params.indexOf("y:") + 2;
    end = params.indexOf("|",start);
    currentMap.y = params.substring(start,end);
  }
  else {
    currentMap.zoomLevel = map.zoomLevel;
    currentMap.x = map.x;
    currentMap.y = map.y;
  }
  currentMap.mmx = map.mmx;
  currentMap.mmy = map.mmy;
  currentMap.mmzoomLevel = map.mmzoomLevel;
  // set map layers from the mapLayers cookie if any, otherwise from DEFAULT_MAP_LAYERS, and reset images
  var mapLayers =  getCookieValue("mapLayersV4");
  if (mapLayers == null) {
    mapLayers = DEFAULT_MAP_LAYERS;
  }
  for (var ix = 0; ix < LAYERS.length; ix++) {
    LAYERS[ix].visible = (mapLayers.indexOf("%2B" + LAYERS[ix].name.toUpperCase()) != -1);
    setLayerImage(LAYERS[ix]);
  }
  if (eventId != null) {
    currentMap.id = eventId;
    currentMap.zoomLevel = 9;
  }
  else {
    currentMap.id = null;
  }
  loadMainMap();
  // set a timer to reload the page in RELOAD_INTERVAL if https for ComCenter
  if (document.location.protocol.indexOf("https") != -1) {
    setTimeout("reloadMainMap()", RELOAD_INTERVAL);
  }
  //NOTE onclick done by mouseReleased when x/ydown = x/yup
  document.getElementById("mapViewport").onmousedown = mousePressed;
  document.onmousemove = mouseMoved;
  document.onmouseup = mouseReleased;
  document.images['mainmap'].onload = mapLoaded;
}

// refreshes the map image from getMainMapUrl("image")
function loadMainMap() {
	//showMainmapLoading();
	document.images['mainmap'].src = getMainMapUrl("image");
	//hideMainmapLoading();
}

// returns the URL for the main map image or the MapInformation window
function getMainMapUrl(type) {
  if (currentMap.id == null) {
    return "map?type=" + type + "&zoomLevel=" + currentMap.zoomLevel 
      + "&width=" + MAP_WIDTH + "&height=" + MAP_HEIGHT + "&layers=" + getMapLayersValue()
      + "&x=" + currentMap.x + "&y=" + currentMap.y;
  }
  else {
    return "map?type=" + type + "&zoomLevel=" + currentMap.zoomLevel 
      + "&width=" + MAP_WIDTH + "&height=" + MAP_HEIGHT + "&layers=" + getMapLayersValue()
      + "&id=" + currentMap.id;
  }
}

// returns the value of the layers parameter for map from mapLayersXXX globals,
// also used as the value of the "mapLayers" cookie
function getMapLayersValue() {
  // background, parks, road, lake and county layers always on
  var layers = "%2BBACKGROUND%2BPARKS%2BROADS%2BLAKES%2BCOUNTIES%2BHIGHLIGHTS";
  for (var ix = 0; ix < LAYERS.length; ix++) {
    if (LAYERS[ix].visible) layers += "%2B" + LAYERS[ix].name.toUpperCase();
  }
  return layers;
}

// sets a timer to reload the page in RELOAD_INTERVAL if https
function reloadMainMap() {
  window.location.reload();
  if (document.location.protocol.indexOf("https") != -1) {
    setTimeout("reloadMainMap()", RELOAD_INTERVAL);
  }
}

// ---------------------- main map interaction functions ------------------------

// sets up for pan (or click)
function mousePressed(event) {
  // W3C passes the event to the handler, IE uses the global window.event
  event = ((event == null) ? window.event : event);
  if (isLeftButton(event.button)) {
    docStartX = event.clientX + document.body.scrollLeft;
    docStartY = event.clientY + document.body.scrollTop;
    originX = docStartX;
    originY = docStartY;
    panning = true;
    preventDefault(event);
  }
}

// moves the image with the mouse drag
function mouseMoved(event) {
  // W3C passes the event to the handler, IE uses the global window.event
  event = ((event == null) ? window.event : event);
  if (isLeftButton(event.button) && panning) {
    var docNextX =  event.clientX + document.body.scrollLeft;
    var docNextY =  event.clientY + document.body.scrollTop;
    var mapDiv = document.getElementById("mapDiv");
    mapDiv.style.left = (docNextX - docStartX) + "px";
    mapDiv.style.top = (docNextY - docStartY) + "px";
    preventDefault(event);
  }
}

// done panning, reloads map
function mouseReleased(event) {
  // W3C passes the event to the handler, IE uses the global window.event
  event = ((event == null) ? window.event : event);
  if (isLeftButton(event.button) && panning) {
    var docEndX =  event.clientX + document.body.scrollLeft;
    var docEndY =  event.clientY + document.body.scrollTop;
    if (originX == docEndX && originY == docEndY) {
      mouseClicked(event);
    }
    else if (docEndX != docStartX && docEndY != docStartY) {
      // MapServlet requires ints
      var xOffset = Math.round((docEndX - docStartX) / ZOOM_LEVELS[currentMap.zoomLevel]);
      var yOffset = Math.round((docStartY - docEndY) / ZOOM_LEVELS[currentMap.zoomLevel]);
      currentMap.x = ((currentMap.x > xOffset) ? currentMap.x - xOffset : 0);
      currentMap.y = ((currentMap.y > yOffset) ? currentMap.y - yOffset : 0);
      setMapCookie();
      loadMainMap();  
    }
    preventDefault(event);
    panning = false;
  }
}

// puts the mapDiv back where it was before the drag (after the new image is loaded)
function mapLoaded() {
  document.getElementById("mapDiv").style.left = "0px";
  document.getElementById("mapDiv").style.top = "0px";
  document.getElementById("mapDiv").width = MAP_WIDTH;
  document.getElementById("mapDiv").height = MAP_HEIGHT;
  document.images['mainmap'].width = MAP_WIDTH;
  document.images['mainmap'].height = MAP_HEIGHT;
}

// click on main map: put up the MapInformation window (not actually an event handler: triggered by
// mouseReleased when mouse start and end are equal)
function mouseClicked(event) {
  // W3C passes the event to the handler, IE uses the global window.event
  event = ((event == null) ? window.event : event);
  // layerX for Firefox, offsetX for IE
  clickX = (event.layerX === undefined ? event.offsetX : event.layerX);
  clickY = (event.layerY === undefined ? event.offsetY : event.layerY); 
  var infoWin = window.open(
    getMainMapUrl("data") + "&clickx=" + clickX + "&clicky=" + clickY,
    "MapInformation",
    "scrollbars=yes,directories=no,location=no,menubar=no,status=no,titlebar=no,toolbar=no,"
      + "resizable=yes,width=400,height=330,top=" + (screen.availHeight - 300) / 2
      + ", left=" + (screen.availWidth - 200) / 2);
  if (infoWin != null) {
    infoWin.focus();
  }
  else {
    alert("The Travel Time Detail window cannot be displayed because popups are disabled.");
  }
  return false;
}

// W3C uses preventDefault(), IE uses the returnValue field
function preventDefault(event) {
  if (event.preventDefault) {
    event.preventDefault();
  }
  else {
    event.returnValue = false;
  }
}

// zooms the map in (href on the zoom in map tool in map.jsp)
function zoomIn() {
  if (currentMap.zoomLevel < ZOOM_LEVELS.length) {
    ++currentMap.zoomLevel;
  }
  setMapCookie();
  loadMainMap();
  for (var i = 0; i < LAYERS.length; i++) {
    setLayerImage(LAYERS[i]);
  }
}

// zooms the map out (href on the zoom out map tool in map.jsp)
function zoomOut() {
  if (currentMap.zoomLevel > 0) {
    --currentMap.zoomLevel;
  }
  setMapCookie();
  loadMainMap();
  for (var i = 0; i < LAYERS.length; i++) {
    setLayerImage(LAYERS[i]);
  }
}

// toggles the given layer (href on map.jsp buttons)
function toggle(layer) {
  layer.visible = !layer.visible;
  // set the "mapLayers" cookie from LAYERS globals
  setCookie("mapLayersV4", getMapLayersValue(), MAP_COOKIE_EXPIRES);
  loadMainMap();
  setLayerImage(layer);
}

// sets the layer button image in map.jsp based on layer.visible
function setLayerImage(layer) {
  filenameSuffix = ZOOM_LEVELS[currentMap.zoomLevel] < layer.minimumZoom ? "Disabled.gif" : ".gif";
  status = ZOOM_LEVELS[currentMap.zoomLevel] < layer.minimumZoom ? " and disabled" : "";
  if (layer.visible) {
	document.images[layer.name].src = "images/" + layer.name + "On" + filenameSuffix;
	document.images[layer.name].title = layer.name + " layer is on" + status;
  }
  else {
    document.images[layer.name].src = "images/" + layer.name + "Off" + filenameSuffix;
    document.images[layer.name].title = layer.name + " layer is off" + status;
  }
}

// sets the cookie from currentMap.zoomLevel, x, and y, with MAP_COOKIE_EXPIRES for the Home map
function setMapCookie() {
  setCookie(currentMap.map.name + MAP_VERSION,
    "zoomLevel:" + currentMap.zoomLevel + "|x:" + currentMap.x + "|y:" + currentMap.y + "|",
    currentMap.map.name == "Home"? MAP_COOKIE_EXPIRES : null);
}

function isLeftButton(button) {
  // why can't we all get along???
  return navigator.userAgent.indexOf("MSIE") == -1 ? (button == 0) : (button == 1);
}

//---------------------- mini map function ------------------------

// sets currentMap.minimapX/minimapY from the minimap click point and refreshes the map and cookie
function minimapClicked(evt) {
  var mousex;
  var mousey;
  if (evt && evt.target) {
    // W3C (target.x is relative to the enclosing <div>)
    mousex = evt.clientX - evt.target.x + window.pageXOffset - document.getElementById("content").offsetLeft;
    mousey = evt.clientY - evt.target.y + window.pageYOffset - document.getElementById("content").offsetTop;
  }
  else if (window.event && window.event.offsetX) {
    // MS-IE
    mousex = window.event.offsetX;
    mousey = window.event.offsetY;
  }
  currentMap.x = currentMap.mmx + Math.round((mousex - MM_WIDTH/2) / ZOOM_LEVELS[currentMap.mmzoomLevel]);
  currentMap.y = currentMap.mmy - Math.round((mousey - MM_HEIGHT/2) / ZOOM_LEVELS[currentMap.mmzoomLevel]);
  setMapCookie();
  loadMainMap();
}

