/**
 * mapTools.js
 *
 * Contains map-related javascript tools for use with the Cheetah archive browser.
 *
 * Dependencies (these must be included in any file that uses mapTools.js, in order):
 *   - browser.js     Browser detection & cross-browser support
 *   - layers.js      Library for layer creation & manipulation
 */

var content;
//var iWidth = 800;
//var iHeight = 400;
var firstImage = "images/firstImage.jpg";
var maxx = 180.0;
var minx = -180.0;
var maxy = 90.0;
var miny = -90.0;

var newMinx = 0;
var newMiny = 0;
var newMaxx = 0;
var newMaxy = 0;
var boxMinx = 0;
var boxMiny = 0;
var boxMaxx = 0;
var boxMaxy = 0;

var mapClickAsRecenter = true;
var mapBoxAsZoom = true;
var allowRubberband = true;
var allowMapClick = true;
var state = "zoomIn";  // zoomOut, pan

// Global vars to save mouse position
var mouseX=0;
var mouseY=0;
var x1=0;
var y1=0;
var x2=0;
var y2=0;
var zminx=0;
var zmaxx=0;
var zmaxy=0;
var zminy=0;

var mapX = 0;
var mapY = 0;
var zoomBoxWidth = 1;

//SEARCHLITE var state = "zoom"; // "pan"

var zooming=false;
var panning=false;
var bottomBorderHeight = 13;

//Scale factor for singe zoom click
var zoomFactor = 3;

//Store previous extent of the map
var lastMinx=-180;
var lastMaxx=180;
var lastMiny=-90;
var lastMaxy=90;

//Store previous extent of the map
var fullMinx=-180.0;
var fullMaxx=180.0;
var fullMiny=-90.0;
var fullMaxy=90.0;



// ----------------------------------------------------------------------------
// Zoom box
// ----------------------------------------------------------------------------

function hideZoomBox()
{
	hideLayer("zoomBoxTop");
	hideLayer("zoomBoxLeft");
	hideLayer("zoomBoxRight");
	hideLayer("zoomBoxBottom");
}


function setZoomBoxColor(color)
{
	setLayerBGColor("zoomBoxTop", color);
	setLayerBGColor("zoomBoxLeft", color);
	setLayerBGColor("zoomBoxRight", color);
	setLayerBGColor("zoomBoxBottom", color);
}


// IE prefers that the events are tied to the map layer, even though that layer is not on top. (WHY!??)
//   NS6 (DOM) requires events to be on the topmost layer (glass pane) no matter what...
function setZoomBoxSettings()
{
  if (browser.isIE55 || browser.isIE60)
  {
    setLayerMouseMove("theMap", getMouse, true);
    setLayerMouseDown("theMap", mapTool, true);
    setLayerMouseUp("theMap", chkMouseUp, true);
  }
  else
  {
    setLayerMouseMove("glass", getMouse, true);
    setLayerMouseDown("glass", mapTool, true);
    setLayerMouseUp("glass", chkMouseUp, true);
  }
}


function setZoomBoxWidth(size)
{
	zoomBoxWidth = size;
}


function showZoomBox()
{
	showLayer("zoomBoxTop");
	showLayer("zoomBoxLeft");
	showLayer("zoomBoxRight");
	showLayer("zoomBoxBottom");
}


function stopEventPropagation(event)
{
  if (browser.isIE50 || browser.isIE55 || browser.isIE60)
  {
    window.event.cancelBubble = true;
    window.event.returnValue = false;
  }
  else if (browser.isNS6 || browser.isNS7 || browser.isMoz09 || browser.isMoz10)
  {
    event.stopPropagation();
    event.preventDefault();
  }
}






// check for mouseup
function chkMouseUp(e)
{
	if (zooming || panning)
  {
		if (mouseX < 0)
		 	mouseX = 0;
		if (mouseX > iWidth)
			mouseX = iWidth;
		if (mouseY < 0)
			mouseY = 0;
		if (mouseY > iHeight)
			mouseY = iHeight;

		mapTool(e);
	}
}


function getImageXY(e)
{
  if (browser.isIE50 || browser.isIE55 || browser.isIE60)
    e = window.event;

	if (browser.isOldNS)
  {
		mouseX=e.pageX;
		mouseY=e.pageY;
	}
  else
  {
		mouseX=e.clientX;
		mouseY=e.clientY;
	}
}


// convert mouse click xy's into map coordinates
function getMapXY(xIn, yIn)
{
	mouseX = xIn;
	var pixelX = (maxx-minx) / iWidth;
	mapX = pixelX * mouseX + minx;
	if ( mapX < -180 || mapX > 180 )
    mapX = null;

	mouseY = iHeight - yIn;
	var pixelY = (maxy-miny) / iHeight;
	mapY = pixelY * mouseY + miny;
	if ( mapY < -90 || mapY > 90 )
    mapY = null;

	return mapX != null && mapY != null;
}


// get the coords at mouse position
function getMouse(e)
{
	getImageXY(e);

  if (zooming)
  {
		if (mouseX < 0)
		 	mouseX = 0;
		if (mouseX > iWidth)
			mouseX = iWidth;
		if (mouseY < 0)
			mouseY = 0;
		if (mouseY > iHeight-bottomBorderHeight)
			mouseY = iHeight-bottomBorderHeight;
		x2 = mouseX;
		y2 = mouseY;

		setClip();

    stopEventPropagation(e);
		return false;
	}
  else if (panning)
  {
		x2=mouseX;
		y2=mouseY;
		panMouse();

    stopEventPropagation(e);
		return false;
	}
  else if ((mouseX>0) && (mouseY>0) && (mouseX<iWidth) && (mouseY<iHeight))
  {
    if (getMapXY(mouseX, mouseY))
		{
		  // round to nearest 100th of a degree to make the numbers prettier and more apropos
		  var x = Math.round( mapX * 100 ) / 100 ;
		  var y = Math.round( mapY * 100 ) / 100 ;
		  window.status = x + ", " + y + " (Geographic Decimal Degrees - WGS 1984)";
		}
		else
		{
		  window.status = ""; // off the edge of the world
		}
	}

  // Returning true on a mouse event insures that window.status will not be
  //   overwritten (browser convention)
  return true;
}



// perform appropriate action with mapTool
function mapTool (e)
{
	getImageXY(e);

	if ((!zooming) && (!panning) &&
		(mouseX >= 0) && (mouseX <= iWidth) &&
		(mouseY >= 0) && (mouseY <= iHeight))
  {
		if (state == "PanDrag")
			startPan(e);
		else
			startZoomBox(e);

    stopEventPropagation(e);
		return false;
	}
  else if (zooming)
  {
		getMouse(e);
		stopZoomBox(e);
	}
  else if (panning)
  {
		getMouse(e);
		stopPan(e);
	}

	return true;
}



// move map image with mouse
function panMouse()
{
	var xMove = x2-x1;
	var yMove = y2-y1;
	var cLeft = -xMove;
	var cTop = -yMove;
	var cRight = iWidth;
	var cBottom = iHeight;
	if (xMove>0)
  {
		cLeft = 0;
		cRight = iWidth - xMove;
	}
	if (yMove>0)
  {
		cTop = 0;
		cBottom = iHeight - yMove;
	}
	clipLayer("theMap",cLeft,cTop,cRight,cBottom);
	moveLayerTo("theMap",xMove,yMove);

	return false;
}



// recenter map is the default option
function recenter(e)
{
	// otherwise we don't have these layers
	if (allowRubberband)
		hideZoomBox();

	if (!getMapXY(mouseX,mouseY))
	{
	  alert("Please click on the map for this function.");
	  return ;
	}
	if (mapClickAsRecenter)
  {
		var widthHalf = Math.abs(maxx - minx) / 2;
		var heightHalf = Math.abs(maxy - miny) / 2;
		newMinx = mapX - widthHalf;
		newMaxx = mapX + widthHalf;
		newMaxy = mapY + heightHalf;
		newMiny = mapY - heightHalf;

		refreshMap();
	}
  else
		customMapClick(mapX,mapY);
}


function refreshMap()
{
  // Force coordinates to be "real world"
  newMinx = Math.max( newMinx , -180.0 );
  newMiny = Math.max( newMiny , -90.0 );
  newMaxx = Math.min( newMaxx , 180.0 );
  newMaxy = Math.min( newMaxy , 90.0 );

  hideZoomBox();
  saveLastExtent();

  parent.MapControlFrame.document.frmMapControlFrame.Lon1.value = newMinx;
  parent.MapControlFrame.document.frmMapControlFrame.Lat1.value = newMiny;
  parent.MapControlFrame.document.frmMapControlFrame.Lon2.value = newMaxx;
  parent.MapControlFrame.document.frmMapControlFrame.Lat2.value = newMaxy;
  parent.MapControlFrame.document.frmMapControlFrame.Action.value = state;

  parent.MapControlFrame.submitMapControlFrame();
}


// clip zoom box layer to mouse coords
function setClip()
{
	if (x1>x2)
  {
		zmaxx=x1;
		zminx=x2;
	}
  else
  {
		zminx=x1;
		zmaxx=x2;
	}

	if (y1>y2)
  {
		zminy=y1;
		zmaxy=y2;
	}
  else
  {
		zmaxy=y1;
		zminy=y2;
	}

	if ((x1 != x2) && (y1 != y2))
  {
		clipLayer("zoomBoxTop", zminx, zmaxy, zmaxx, zmaxy+zoomBoxWidth);
		clipLayer("zoomBoxLeft", zminx, zmaxy, zminx+zoomBoxWidth, zminy);
		clipLayer("zoomBoxRight", zmaxx-zoomBoxWidth, zmaxy, zmaxx, zminy);
		clipLayer("zoomBoxBottom", zminx, zminy-zoomBoxWidth, zmaxx, zminy);
	}
}



function setExtent(_minx,_miny,_maxx,_maxy)
{
	minx = _minx;
	miny = _miny;
	maxx = _maxx;
	maxy = _maxy;
}



function setState(newState)
{
	state = newState;
  if (state == "PanDrag")
  {
    if (browser.isIE55 || browser.isIE60)
      setLayerCursor("theMap", "move");
    else
      setLayerCursor("glass", "move");
  }
	else
  {
    if (browser.isIE55 || browser.isIE60)
      setLayerCursor("theMap", "crosshair");
    else
      setLayerCursor("glass", "crosshair");
  }

	if (state == "zoomIn")
  {
		mapBoxAsZoom = true;
		setZoomBoxColor("#ff0000");
		setZoomBoxWidth(1);
	}
  else if (state == "zoomOut")
  {
		mapBoxAsZoom = true;
		setZoomBoxColor("#ff0000");
		setZoomBoxWidth(1);
	}
  else if (state == "selectDrag")
  {
		mapBoxAsZoom = true;
		setZoomBoxColor("#FFFF00");
		setZoomBoxWidth(2);
	}
  else if (state == "PanDrag")  {
	}
}



// Start panning the map image
function startPan(e)
{
	moveLayerTo("theMap",0,0);

	getImageXY(e);
	// keep it within the MapImage
	if ((mouseX<iWidth) && (mouseY<iHeight))
  {
		if (panning)
    {
			stopPan(e);
		}
    else
    {
			x1=mouseX;
			y1=mouseY
			x2=x1+1;
			y2=y1+1;
			panning=true;
		}
	}
	return false;

}


// Start dragging the zoom box
function startZoomBox(e)
{
	getImageXY(e);

	if (!allowRubberband)
  {
		stopZoomBox(e);
	}
  else
  {
		// keep it within the MapImage
		if ((mouseX < iWidth) && (mouseY < iHeight-bottomBorderHeight))
    {
			if (!zooming)
      {
				x1 = mouseX;
				y1 = mouseY;
				x2 = x1+1;
				y2 = y1+1;

				zooming = true;

        clipLayer("zoomBoxTop", x1, y1, x2, y2);
				clipLayer("zoomBoxLeft", x1, y1, x2, y2);
				clipLayer("zoomBoxRight", x1, y1, x2, y2);
				clipLayer("zoomBoxBottom", x1, y1, x2, y2);

				showZoomBox();
			}
		}
    else
    {
			if (zooming)
      {
				stopZoomBox(e);
			}
		}
	}

	return false;
}


// Stop panning the map image
function stopPan(e)
{
	if ((Math.abs(x2-x1) < 2) && (Math.abs(y2-y1) < 2))
  {
		// the move is too small
		panning=false;
		recenter(e);
	}
  else
  {
		window.scrollTo(0,0);  //why?

		panning=false;
		var width = Math.abs(maxx - minx);
		var height = Math.abs(maxy - miny);
		var tempLeft=minx;
		var tempRight=maxx;
		var tempTop=maxy;
    var tempBottom=miny;
		var ixOffset = x2-x1;
		var iyOffset = y1-y2;
		pixelX = width / iWidth;
		var theY = iHeight - zmaxy;
		pixelY = height / iHeight;
		var xOffset = pixelX * ixOffset;
		var yOffset = pixelY * iyOffset;
		newMaxy = maxy - yOffset;
		newMaxx = maxx - xOffset;
		newMinx = minx - xOffset;
		newMiny = miny - yOffset;

		// AP specific setting
		attributeUpdate = false;

		refreshMap();
	}

	return true;

}




// Stop drawing the zoom box rubberband, and zoom in.
function stopZoomBox(e)
{
	zooming=false;
	if ((zmaxx <zminx+4) && (zmaxy < zminy+4))
  {
		if (state == "zoomIn")
    {
			zoomin(e);
		}
    else if (state == "zoomOut")
    {
			zoomout(e);
		}
    else if (state == "selectDrag")
    {
			selectpoke(e);
		}
    else
    {
			recenter(e);
		}
	}
  else
  {
		var width = Math.abs(maxx - minx);
		var height = Math.abs(maxy - miny);
		var pixelX = width / iWidth;
		var theY = iHeight - zmaxy;
		var pixelY = height / iHeight;
		newMaxy = pixelY * theY + miny;
		newMaxx = pixelX * zmaxx + minx;
		newMinx = pixelX * zminx + minx;
		theY = iHeight - zminy;
		pixelY = height / iHeight;
		newMiny = pixelY * theY + miny;

		if (mapBoxAsZoom)
    {
			if (state == "zoomOut")
      {
				percentX = (maxx-minx)/(newMaxx-newMinx);
				percentY = (maxy-miny)/(newMaxy-newMiny);
				percent = (percentX+percentY)/2;

				widthH = (maxx-minx)/2;
				heightH = (maxy-miny)/2;
				cx = newMinx + widthH;
				cy = newMiny + heightH;

				newMinx = cx - percent * widthH;
				newMiny = cy - percent * heightH;
				newMaxx = cx + percent * widthH;
				newMaxy = cy + percent * heightH;
			}
			refreshMap();
		}
    else
			customMapBox(newMinx, newMiny, newMaxx, newMaxy);

	}
	return true;
}



//Zoom in/Zoom out functions stolen from aimsNavigation.js to zoom to a single click
// zoom in around mouse click
function zoomin(e)
{
	if (!getMapXY(mouseX,mouseY))
	{
	  alert("Please click on the map for this function.");
	}
  else
  {
  	xDistance = Math.abs(maxx-minx);
	  yDistance = Math.abs(maxy-miny);
  	xHalf = xDistance / 2;
	  yHalf = yDistance / 2;

  	newMinx = mapX - (xHalf/zoomFactor);
	  newMaxx = mapX + (xHalf/zoomFactor);
  	newMaxy = mapY + (yHalf/zoomFactor);
	  newMiny = mapY - (yHalf/zoomFactor);

  	refreshMap();
  }
}



// Zoom out given the established new extent
function zoomout(e)
{
	if (!getMapXY(mouseX,mouseY))
	{
	  alert("Please click on the map for this function.");
	  return ;
	}

	xDistance = Math.abs(maxx-minx);
	yDistance = Math.abs(maxy-miny);

	newMinx = mapX - (xDistance*zoomFactor/2);
	newMaxx = mapX + (xDistance*zoomFactor/2);
	newMaxy = mapY + (yDistance*zoomFactor/2);
	newMiny = mapY - (yDistance*zoomFactor/2);


	refreshMap();
}



// If the user just does a single click, then the zoom box is just a point.
function selectpoke(e)
{
  if (!getMapXY(mouseX,mouseY))
  {
    alert("Please click on the map for this function.");
  }
  else
  {
    newMinx = mapX;
    newMaxx = mapX;
    newMaxy = mapY;
    newMiny = mapY;

    refreshMap();
  }
}



//Save the last extent of the map so you can zoom to the previous extent
function saveLastExtent()
{
	lastMinx=minx;
	lastMaxx=maxx;
	lastMiny=miny;
	lastMaxy=maxy;

}



function clearSelect(currentState)
{
  parent.MapControlFrame.document.frmMapControlFrame.Action.value = "clearSelect";
  parent.MapFrame.setState("clearSelect");
  refreshMap();
  parent.MapControlFrame.document.frmMapControlFrame.Action.value = currentState
  parent.MapFrame.setState(currentState);
}

function zoomToPreviousExtent(currentState)
{
  parent.MapControlFrame.document.frmMapControlFrame.Action.value = "PreviousExtent";
  parent.MapFrame.setState("PreviousExtent");

  //TODO See if we can avoid the need to remember and reset the state when doing things like this
	//reset the new bounding box to the one from the previos request
	newMinx = lastMinx;
	newMaxx = lastMaxx;
	newMiny = lastMiny;
	newMaxy = lastMaxy;

	refreshMap();

  parent.MapControlFrame.document.frmMapControlFrame.Action.value = currentState
  parent.MapFrame.setState(currentState);
}

function zoomToFullExtent(currentState)
{
  parent.MapControlFrame.document.frmMapControlFrame.Action.value = "FullExtent";
  parent.MapFrame.setState("FullExtent");

	//reset the new bounding box to the one from the previos request
	newMinx = fullMinx;
	newMaxx = fullMaxx;
	newMiny = fullMiny;
	newMaxy = fullMaxy;

	refreshMap();

  parent.MapControlFrame.document.frmMapControlFrame.Action.value = currentState
  parent.MapFrame.setState(currentState);
}




function panDirectional(currentState, direction)
{
  // sanity check:
  if ( ( direction == 1 && maxy >= 89 )  || // north
       ( direction == 3 && maxx >= 179 ) || // east
       ( direction == 5 && miny <= -89 ) || // south
       ( direction == 7 && minx <= -179 ) ) // west
  {
    alert("Cannot move map further in that direction");
    return ;
  }

  parent.MapControlFrame.document.frmMapControlFrame.Action.value = "PanDirectional";
  parent.MapControlFrame.document.frmMapControlFrame.Magnitude.value = zoomFactor;
  parent.MapFrame.setState("PanDirectional");

  parent.MapControlFrame.document.frmMapControlFrame.ActionParm.value = direction;

  refreshMap();

  parent.MapControlFrame.document.frmMapControlFrame.Action.value = currentState
  parent.MapFrame.setState(currentState);
}



function clearSelection(currentState)
{
  parent.MapControlFrame.document.frmMapControlFrame.Action.value = "clearSelection";
  parent.MapFrame.setState("clearSelection");

  refreshMap();

  parent.MapControlFrame.document.frmMapControlFrame.Action.value = currentState
  parent.MapFrame.setState(currentState);
}
