/*******************************************/     

        var timeOut;
	var binHomeAlias;
        var mapHomeAlias;
        var latStr;
        var lonStr;
        var nvPairs;
        var idURL;
        var tnURL;

        var expandRelease;
        var expandTimeofDay;
        var expandCamera;
        var expandBackground;

	var releaseMenuInit = 0;	
        var consoleWin = null;	
	var bdrWidth;
        var winHeightMin;
        var winWidthMin;

	var publicState;
	var useCookie;

	var resList = new Array(1.666667, 4.0, 8.0, 16.0, 32.0, 64.0);

	/* Global variables to be modified by menu selections */
	var background;
	var release;
	var panSelectZoom;
	var foreground;
	var dayNight

	/*******************************************/     
	/* Changed by window resizes */     
	var wHeight;
	var wWidth;
	/*******************************************/     

	/* Global variables to be modified by mapEvents */
	var cLat;
	var cLon;
        var leftLon;
        var topLat;
	var resIndex;
        var res;
        var mapWidth;
        var mapHeight;

	// Create the cookie object and initialize the link value
        var wmCookie    = new Cookie(document, "x6_webmap", 2);

// Get the mouse X offset position (if any), wrt its parent layer
function getOffsetX(imgId) {
    var img = getElementById(imgId);	
    var curLeft = 0;

    if(img.offsetParent) {
 	curLeft += img.offsetLeft;
    }
    else if(img.x) {
        curLeft += img.x;
    }

    return curLeft;
}

// Get the mouse Y offset position (if any), wrt its parent layer
function getOffsetY(imgId) {
    var img = getElementById(imgId);	
    var curTop = 0;

    if(img.offsetParent) {
	curTop += img.offsetTop;
    }
    else if(img.y) {
        curTop += img.y;
    }

    return curTop;
}

// Gets element that was clicked on out of event
function eventTarget(e) {   
    return((e.target ? e.target : window.event.srcElement));
}

// Get the mouse X/Y position, convert to lat/lon and display
function trackMouse(e, parentBox) {
    var obj = eventTarget(e);

    e.returnValue = false;

    updateLatLon(y2Lat(getMouseY(e) + posYwrtParent(obj, parentBox)), 
		 x2Lon(getMouseX(e) + posXwrtParent(obj, parentBox)));

    return false; 
}

// Return the X mouse position for various WWW client types
function getMouseX(e) {
    var posX = (e.offsetX ? e.offsetX : e.layerX);
    var undefined;
             
    // Sanity check when IE returns "undefined"
    if(posX == undefined) {
        posX = 0;
    }

    if(posX > (res * 360 - 1)) {
        posX = res * 360 - 1;
    }

    return posX;
}

// Return the Y mouse position for various WWW client types
function getMouseY(e) {
    var posY = (e.offsetY ? e.offsetY : e.layerY);
    var undefined;
             
    // Sanity check when IE returns "undefined"
    if(posY == undefined) {
       posY = 0;
    }

    if(posY > res * 180 - 1) {
       posY = res * 180 - 1;
    }

    return posY;
}

// Find X mouse position wrt a parent
function posXwrtParent(obj, parentId)
{
  var posX = 0;

  if(obj.offsetParent) {
    while(obj.offsetParent && obj.id != parentId) {
	  posX += obj.offsetLeft;
          obj  = obj.offsetParent;
    }
  }
  else if(obj.x) {
      posX += obj.x;
  }

  return posX;
}

// Find X mouse position wrt a parent
function posYwrtParent(obj, parentId)
{ 
   var posY = 0;

   if(obj.offsetParent) {
      while(obj.offsetParent && obj.id != parentId) {
	posY += obj.offsetTop;
	obj   = obj.offsetParent;
      }
   }
   else if(obj.y) {
      posY += obj.y;
   }

   return posY;
}

// Convert X mouse position to longitude
function x2Lon(x) {
    var lon = leftLon + (x + 0.5)/res;

    if(lon > 360.0) {
      lon -= 360;
    }

    return lon;
}

// Convert Y mouse position to latitude
function y2Lat(y) {
    return (topLat - (y - 1.5)/res);

// OLD   return (topLat - (y + 0.5)/res);
}

// Convert latitude into map pixel position
function lat2Y(lat) {

// return (res * (topLat - lat) - 0.5);

    return (res * (topLat - lat) + 1.5);
}

// Convert longitude into map pixel position
function lon2X(lon) {
    var tLon = lon - leftLon;

    if(tLon < 0)
	tLon += 360.0;

    return (res * tLon - 0.5);
}

// Paint the current latitude/longitude on the screen
function updateLatLon(lat, lon) {
    var label;
    var latStr, lonStr;

    if(lat < 0) {
      label = " S / ";
    }
    else {
      label = " N / ";
    }

    lat = Math.abs(lat);

    // Build latitude string
    // Fix for browsers that truncate floats e.g. 20.0 --> 20	    
    if(Math.abs(Math.round(lat) - lat) > 0.1) {

	latStr = sprintf("%5.1f&deg%s", lat, label);
    }
    else {
	latStr = sprintf("%5.0f.0&deg%s", lat, label);
    }

    // Build longitude string
    // Fix for browsers that truncate floats e.g. 20.0 --> 20	    
    if(Math.abs(Math.round(lon) - lon) > 0.1) {
	lonStr = sprintf("%5.1f&deg E", lon);
    }
    else {
	lonStr = sprintf("%5.0f.0&deg E", lon);
    }
 
    getElementById("latlonStr").innerHTML = latStr + lonStr;
}

// What the name says
function getFrameDocFromFrame(frame) {
    var iFrameDoc;

    if(frame.contentDocument) { 
	// For NS 6
	iFrameDoc  = frame.contentDocument;
    }
    else if(frame.contentWindow) { 
	// For IE5.5 and IE6
	iFrameDoc = frame.contentWindow;		    
    }
    else if(frame.document) { // For IE5
	iFrameDoc = frame.document;				
    }
    return iFrameDoc;
}

// Open a window and fill it with the results of a CGI script.
// The window contents will tell us which observation polygon,
// if any, the mouse click fell in.
function selectHandler(lat, lon, idFrameName, tnFrameName) {
    var idFrame = getElementById(idFrameName);
    var tnFrame = getElementById(tnFrameName);
    var url = binHomeAlias + "latlon2ImageIdTHEMIS.pl?clat=" + lat + "&clon=" + lon + 
	"&ds=" + foreground + "&dn=" + dayNight + "&rel=" + release + 
	"&public=" + publicState + "&res=" + res;

    // debug('url: ' + url);

    // Prepare to load idList frame
    getFrameDocFromFrame(idFrame).location.replace(url + "&tnl=0");

    // Prepare to load thumbnail frame
    getFrameDocFromFrame(tnFrame).location.replace(url + "&tnl=1");
}

// The map window may be larger than the 
// true size of the current map. Check for 
// this padding and return the valid width 
// of the map
function getImgHeight(mapName) {
   var img = getElementById(mapName);		

   if(img.height > res * 180 - 1) {
      return (res * 180 - 1);
   }
   else {
      return img.height;
   }
}

// The map window may be larger than the 
// true size of the current map. Check for 
// this padding and return the valid width 
// of the map
function getImgWidth(mapName) {
   var img = getElementById(mapName);		

   if(img.width > res * 360 - 1) {
      return (res * 360 - 1);
   }
   else {
      return img.width;
   }
}

// Leftmost longitude is 1/2 screen width "left" of current center.
function getLeftLon(cLon, mapWidth, nextRes) {
   var lLon = cLon - mapWidth/(nextRes * 2);

   if(lLon < 0.0) {
     lLon += 360;
   } 
   
   return lLon;
}

// Top latitude is 1/2 screen height above current center
function getTopLat(cLat, mapHeight, nextRes) {
   if(cLat + mapHeight/(nextRes * 2) > 90.0) {

   // If the resulting image is closer than 1/2 the
   // map window height to the top, set the top latitude
   // to 90. This is the best the cuting utility gives us.

     return 90;
   }
   else if(cLat - mapHeight/(nextRes * 2) < -90.0) {

   // Force top latitude is 1/2 map window height up from
   // -90. This is the best the cutting utility can give us.

      return (-90.0 + mapHeight/nextRes);
   }
   else { // Top latitude is 1/2 map window height above center latitude.
      return (cLat + mapHeight/(nextRes * 2));
   }
}

function mapEvent(e, mapName, parentBox) {
   var nextRes;
   var obj    = eventTarget(e);
   var slider = getElementById('slider');	

   e.returnValue = false;

   // Shouldn't have propagated the event here. Return;
   if(obj.id != mapName && obj.id != "crosshair2") { 
     return false; 
   }

   // Get the latest mouse X/Y position, convert to lat/lon
   var x = getMouseX(e) + posXwrtParent(obj, parentBox) ;
   var y = getMouseY(e) + posYwrtParent(obj, parentBox);

   var tLat = y2Lat(y);
   var tLon = x2Lon(x);
	
   if(panSelectZoom == 0) { // Panning

   // Displayed resolution remains the same

      nextRes = res; 
   }
   else if(panSelectZoom == 2) {  // Zooming in

      // Increase the resolution if possible

      if(resIndex < resList.length - 1) {
	resIndex++;
        nextRes = resList[resIndex]; 
      }
      else {
         nextRes = res; 
      }
   }
   else if(panSelectZoom == 3) {  // Zooming out

	      // Decrease the resolution if possible
      if(resIndex > 0) {
	resIndex--;
        nextRes = resList[resIndex]; 
      }
      else {
         nextRes = res; 
      }
   }
   else if(panSelectZoom == 1) {  // Selecting
       selectHandler(tLat, tLon, "idFrameAlt", "tnFrame");
			
       // Update crosshair position
       updateCrosshair(mapName, tLat, tLon);
       drawCrosshair(mapName);
       return false; 
   }

   cLat = tLat;
   cLon = tLon;

   // The map window may be larger than the true size of the current
   // map. Check and adjust as needed.

   // Leftmost longitude is 1/2 screen width "left" of current center.
   leftLon = getLeftLon(cLon, getImgWidth(mapName), nextRes);
        
   topLat = getTopLat(cLat, getImgHeight(mapName), nextRes);

   res = nextRes;
  
   // Render the map
   refreshMap(mapName);

   updateLatLon(cLat, cLon);

   ///////////////////////////////////////////
   // Update the slider bar and value
   slider.resIndex = resIndex;

   moveSlider(slider);

   return false; 
}

function rescaleMap(sliderRes) {

   resIndex = sliderRes;    // Set global map scale index
   res = resList[resIndex]; // Set global map scale

   // Leftmost longitude is 1/2 screen width "left" of current center.
   leftLon = getLeftLon(cLon, getImgWidth('map'), res);
   topLat  = getTopLat(cLat, getImgHeight('map'), res);
  
   // Render the map
   refreshMap('map');

   updateLatLon(cLat, cLon);
}

function debug(msg) {	
    if((consoleWin == null) || (consoleWin.closed)) {
	consoleWin = window.open("", "console", "width=200,height=600,resizable,scrollbars");
	consoleWin.document.open("text/plain");	
    }
    consoleWin.document.writeln(msg);
}

function initializeLoadingImg(mapName, loadingName) {
    var mapImg     = getElementById(mapName);		
    var loadingImg = getElementById(loadingName);		

    // Attach loading image to map
   mapImg.loadingImg = loadingImg;
}

// Turn off everything associated with the timeout image display.
function hideLoadingImg(mapName) {
   var mapImg     = getElementById(mapName);		
   var loadingImg = getElementById(mapName).loadingImg;		

   // If we're called before tool initialization completes. Exit.
   if(!loadingImg) {
       return;	   
   }

   mapImg.completed = true;
   window.clearTimeout(timeOut);
   loadingImg.style.display = "none";		
}

function showLoadingImg() {
    var mapName = "map";
    var mapImg = getElementById(mapName);		
    var width  = getImgWidth(mapName);
    var height = getImgHeight(mapName);

    // Only show loading GIF if map is still downloading
    if(mapImg.completed == true) {

       // Hide the image
       loadingImg.style.display = "none";		

       // Explictly clear timeout in case browsers are faulty
       window.clearTimeout(timeOut);
    }
    else {
	mapImg.loadingImg.src = mapHomeAlias + "/img/animateLoad.gif";
	mapImg.loadingImg.style.display  = "block";
	mapImg.loadingImg.style.position = "absolute";
	mapImg.loadingImg.style.left     = getOffsetX(mapImg.id) + width/2 - 80  + "px";
	mapImg.loadingImg.style.top      = getOffsetY(mapImg.id) + height/2 + "px";
    }
}

function initializeCrosshair(mapName, crsshairName, lat, lon) {
    var mapImg = getElementById(mapName);		
    var chImg  = getElementById(crsshairName);		

    // Attach crosshair image to map
    mapImg.crss = chImg;

    updateCrosshair(mapName, lat, lon);
}

function updateCrosshair(mapName, lat, lon) {
    var mapImg = getElementById(mapName);		

    mapImg.crss.lon = lon;
    mapImg.crss.lat = lat;
}

function drawCrosshair(mapName) {
    var map    = getElementById(mapName);		
    var img    = map.crss;		
    var width  = getImgWidth(mapName);
    var height = getImgHeight(mapName);

    // If we're called before initialization completes. Exit.
    if(!img) return;	   

    var x = lon2X(img.lon);
    var y = lat2Y(img.lat);

   // Turn off the crosshair when it's out of bounds
   if(x < 0 || x > width || y < 0 || y > height) {
       img.style.display = "none";
   }
   else {
       img.style.display  = "block";
       img.style.position = "absolute";
       img.style.left = getOffsetX(map.id) + x - (img.width  - 1)/2 + "px";
       img.style.top  = getOffsetY(map.id) + y - (img.height - 1)/2 + "px";
   }
   return true;
}

function refreshMap(mapName) {      
    var img = getElementById(mapName);		
    var undefined;
    var url;

    var bgMapColor = "3b7aa6";  

    // OSX NS img.complete is not functioning. Use our own boolean for the load.
    img.completed = false;

    // Delay display of "loading..." GIF for 1 second
    timeOut = window.setTimeout('showLoadingImg()', 1000);

    // Create the URL for the new map image
    url = binHomeAlias + "compositeRasterTHEMIS.pl?scale=" + res + "&lat=" + cLat + 
	"&lon=" + cLon + "&bg=" + background + "&dn=" + dayNight + 
	"&fg=" + foreground + "&rel=" + release + "&wh=" + wHeight + "&ww=" + wWidth + 
	"&bdr=" + bdrWidth + "&col=" + bgMapColor + "&public=" + publicState;

    // Set the map image
    img.src = url;

    updateMapState();
}

function buttonOverOutEvent(operation, statusElmt, event) {
   var statusStr = getElementById(statusElmt);	

   // display current mode 
   switch(operation) {
     case 0:  statusStr.innerHTML = "Recenter";      break;
     case 1:  statusStr.innerHTML = "Select";   break;
     case 2:  statusStr.innerHTML = "Zoom In";  break;
     case 3:  statusStr.innerHTML = "Zoom Out"; break;
     case 4:  statusStr.innerHTML = "Link to this Page"; break;

     case 9:  statusStr.innerHTML = "Select visible or infrared"; break;
     case 10: statusStr.innerHTML = "View Quick Start Guide"; break;
     case 11: statusStr.innerHTML = "Select day or night"; break;
     case 12: statusStr.innerHTML = "Select a release"; break;
     case 14: statusStr.innerHTML = "Change map background"; break;
     case 15: statusStr.innerHTML = "Image links appear below"; break;
     case 16: statusStr.innerHTML = "<- Choose among operators"; break;
     case 17: statusStr.innerHTML = "Current latitude and longitude"; break;

     case 18: statusStr.innerHTML = "Zoom out one step"; break;
     case 19: statusStr.innerHTML = "Zoom in one step"; break;
     case 20: statusStr.innerHTML = sprintf("%5.1f pixels/degree", resList[getElementById('slider').resIndex]); break;
     default: statusStr.innerHTML = "Help";   break;
   }
}

function sliderZoom(operation, statusElmt, res) {
  var statusStr = getElementById(statusElmt);	

  // display slider zoom event
  switch(operation) {
     case 0:  statusStr.innerHTML = sprintf("Zoom out to %5.1f ppd", resList[res]); break;
     case 1:  statusStr.innerHTML = sprintf("Zoom in to %5.1f ppd", resList[res]);  break;
     case 2:  statusStr.innerHTML = sprintf("%5.1f pixels/degree", resList[res]);  break;
     default: statusStr.innerHTML = "Help";    break;
  }
}

function popupGuide(url, titleTarget) {
   var helpWin = window.open(url, titleTarget, "width=750,height=600,resizable,scrollbars");
}

// Set mode depending on which icon was clicked
function buttonEvent(operation, opStr, statusElmt) {	
  var img;

  var statusStr = getElementById(statusElmt);	

  if(operation == 4) {
    document.location = getElementById(opStr).url;
  }
  else if(operation == 5) {
    statusStr.innerHTML = "Help";
    popupGuide(mapHomeAlias + "/ug/help.html", "Web Map Help");
  }	
  else
  {       // Turn off previous mode...
    switch(panSelectZoom) {
      case 0: img = getElementById("pan");		
          img.src = mapHomeAlias + "/img/pan_icon.gif";
          break;
   
      case 1: img = getElementById("select");		
          img.src = mapHomeAlias + "/img/pointer_icon.gif";
          break;
 
      case 2: img = getElementById("zoomIn");		
          img.src = mapHomeAlias + "/img/zoom_plus_icon.gif";
          break;
   
      case 3: img = getElementById("zoomOut");		 
          img.src = mapHomeAlias + "/img/zoom_minus_icon.gif";
          break;
    }
   
    // and turn On current mode 
    switch(operation) {
      case 0: img = getElementById("pan");		
          img.src = mapHomeAlias + "/img/pan_iconInvert.gif";
          statusStr.innerHTML = "Recenter";
          break;
   
      case 1: img = getElementById("select");		
          img.src = mapHomeAlias + "/img/pointer_iconInvert.gif";
          statusStr.innerHTML = "Select";
          break;
   
      case 2: img = getElementById("zoomIn");		
          img.src = mapHomeAlias + "/img/zoom_plus_iconInvert.gif";
          statusStr.innerHTML = "Zoom In";
          break;
   
      case 3: img = getElementById("zoomOut");		 
          img.src = mapHomeAlias + "/img/zoom_minus_iconInvert.gif";
          statusStr.innerHTML = "Zoom Out";
          break;
    }
    panSelectZoom = operation;

    updateMapState();
  }	 
}

// Modify variable "release" based on menu choice 
function releaseEvent(choice, mapName) {

  // Only refresh map if something has changed
  if(release != choice) {
     release = choice + 0;
     refreshMap(mapName);
  }
}

// Modify variable "dayNight" based on menu choice 
function dayNightEvent(choice, mapName) {

  // Only refresh map if something has changed
  if(dayNight != choice) {
     dayNight = choice;
     refreshMap(mapName);
  }
}

// Modify variable "foreGrndDS" based on menu choice 
function foregroundEvent(choice, mapName) {

// Only refresh map if something has changed
  if(foreground != choice) {
     foreground = choice;
     refreshMap(mapName);
  }	
}
	
// Modify variable "background" based on menu choice 
function backgroundEvent(choice, mapName) {

  // Only refresh map if something has changed
  if(background != choice) {
    background = choice;
     refreshMap(mapName);
  }	
}

// Create URL string of the map's state
function getMapState() {

   return(binHomeAlias + "themis.pl?clat=" + cLat + 
   "&clon=" + cLon + "&res=" + resIndex + 
   "&psz=" + panSelectZoom + 
   "&fg="  + foreground + 
   "&dn="  + dayNight + 
   "&rel=" + release +
   "&bgrnd=" + background + 
   "&cookie=" + useCookie);
}

// Copy the new map state into the link anchor and cookie
function updateMapState() {
  var tlink = getElementById("saveLink");

  tlink.url =  getMapState();

  // If we're using cookies AND cookie link has been initialized
  // update the state now.
  if(useCookie && wmCookie.wmLink) { 
     wmCookie.wmLink = tlink.url;

     // Store the cookie, and reset the expiration clock
     wmCookie.store();
  }
}


// This sets up each of the menus.
window.onload = function() {
  initializeMenu("releaseMenu",  "releaseActuator", releaseMenuInit);
  initializeMenu("backgroundMenu", "backgroundActuator", background);
  initializeMenu("timeMenu", "timeActuator", dayNight);
  initializeMenu("cameraMenu", "cameraActuator", foreground);
  initializeSlider("slider", "sliderBar", resIndex, resList.length - 1);

  // Open menus as requested
  if(expandRelease)     getElementById("releaseActuator").onclick();
  if(expandTimeofDay)  getElementById("timeActuator").onclick();
  if(expandCamera)     getElementById("cameraActuator").onclick();
  if(expandBackground) getElementById("backgroundActuator").onclick();

  initializeLoadingImg("map", "loading");
  initializeCrosshair("map", "crosshair2", cLat, cLon);

  // Get the map's dimensions
  mapWidth  = getImgWidth("map");
  mapHeight = getImgHeight("map");

  // Adjust the position of the left-hand side longitude 
  leftLon = getLeftLon(cLon, mapWidth, res);
         
  // Adjust the position of the top of the screen
  topLat  = getTopLat (cLat, mapHeight, res);

  // Initialize the operator icons
  switch(panSelectZoom) { 
    case 0:  buttonEvent(0, "pan", "modeStatus"); break;
    case 1:  buttonEvent(1, "select", "modeStatus"); break;
    case 2:  buttonEvent(2, "zoomIn", "modeStatus"); break;
    case 3:  buttonEvent(3, "zoomOut", "modeStatus"); break;
    default: buttonEvent(2, "zoomIn", "modeStatus"); 
  }

  // Load the previous webmap state if it exists and is valid
  if(useCookie) { 
    if(wmCookie.load()) {

      // Load cookie state if != current state
      if(getMapState() != unescape(wmCookie.wmLink)) {
         document.location = unescape(wmCookie.wmLink);
      }
    }
    else {  // Set and store map state in link and cookie
             wmCookie.wmLink = " ";
             updateMapState();
    }
  }
}
