// -----------------------------------------------------------------
//								 ArcWeb USA Site Starters 
//            Environmental Systems Research Institute
//                   Redlands, CA
// -----------------------------------------------------------------
// Class    : map 
// Purpose  : Abstracts map extent management issues.
// -----------------------------------------------------------------
// Calls    :
// Called by:
// -----------------------------------------------------------------
// Arguments:
// Globals  :
// Returns  :
// -----------------------------------------------------------------
// Notes    :
// -----------------------------------------------------------------
// History  :
// =================================================================

function map(left, top, width, height, widths, extent) {

	var PAN_FACTOR = 0.4;

	var m_rctExtent;     // Extent of the map in map units.  
											 // Can be set by a number of methods
											 // (e.g. setExtent, recenter, etc.).

	var m_iCurrentLevel; // Current level of the map.
	//alert(findPosX(Container1));
	//alert(findPosY(Container1));
	var m_iTagLeft = parseInt(left) + findPosX(Container1);     // These are dimensions, in
	var m_iTagTop = parseInt(top)+ findPosY(Container1);       // page units, which describe
	var m_iTagWidth = parseInt(width);   // the position of the image 
	var m_iTagHeight = parseInt(height); // tag representing the map.
	var m_arrWidths = widths;  // Array of levels widths to associated with the map
					    							 // as an alternate means of zooming in or out.
		// Set the extent.

	setExtent(extent);
    /*mapXMin = extent.getLeft();
	mapXMax = extent.getRight();
	mapYMin = extent.getBottom();
	mapYMax = extent.getTop();*/
	
		// Method assignments.

	this.getTagLeft = getTagLeft;
	this.getTagTop = getTagTop;
	this.getTagWidth = getTagWidth;
	this.getTagHeight = getTagHeight;

	this.setExtent = setExtent;
	this.getExtent = getExtent;

	this.setLevel = setLevel;
	this.getLevel = getLevel;

	this.isEventOverMap = isEventOverMap;
	this.toMapPoint = toMapPoint;
	this.toPagePoint = toPagePoint;

	this.recenter = recenter;
	this.zoom = zoom;

	this.moveEast = moveEast;
	this.moveNorth = moveNorth;
	this.moveSouth = moveSouth;
	this.moveWest = moveWest;
	this.moveNorthEast = moveNorthEast;
	this.moveSouthEast = moveSouthEast;
	this.moveNorthWest = moveNorthWest;
	this.moveSouthWest = moveSouthWest;	

	this.updateWidths = updateWidths;
	//this.makeRectFromCenter = makeRectFromCenter;
	this.getAdjustedRect = getAdjustedRect;
	this.getLevelRect = getLevelRect;
	this.handleOverviewClick = handleOverviewClick;
	//this.buildLevelRect = buildLevelRect;	

  // -----------------------------------------------
  // --------------- Public Methods ----------------
  // -----------------------------------------------
	// The public methods for this class fall in fall 
  // into one of three categories.

  // -----------------------------------------------
	// Category 1: Methods that have to do with the 
  //             extent of the map.
  // -----------------------------------------------

	function getExtent() {
		return m_rctExtent;
	}

	function setExtent(rctExtent) {
		//if (m_rctExtent != null)
		//alert("previous width = " + rctExtent.getWidth());
		m_rctExtent = getAdjustedRect(rctExtent, m_iTagWidth, m_iTagHeight);
		//alert("new width = " + m_rctExtent.getWidth());
		m_iCurrentLevel = findLevel(m_rctExtent);
	}

	function getLevel() {
		return m_iCurrentLevel;
	}

	function setLevel(level) {
		//if (m_rctExtent != null)
		//	alert("previous width = " + m_rctExtent.getWidth());	
		m_iCurrentLevel = level;
		m_rctExtent = getAdjustedRect(buildLevelRect(m_iCurrentLevel), 
                                  m_iTagWidth, 
                                  m_iTagHeight);
        //alert("new width = " + m_rctExtent.getWidth());
	}

	function moveEast() {

		recenter(
						 new point(
											 m_rctExtent.getCenter().x + (m_rctExtent.getWidth() * PAN_FACTOR), 
											 m_rctExtent.getCenter().y
											 )
						);
		
	}

	function moveNorth() {

		recenter(
						 new point(
											 m_rctExtent.getCenter().x, 
											 m_rctExtent.getCenter().y + (m_rctExtent.getHeight() * PAN_FACTOR)
											 )
						);
		
	}

	function moveSouth() {

		recenter(
						 new point(
											 m_rctExtent.getCenter().x, 
											 m_rctExtent.getCenter().y - (m_rctExtent.getHeight() * PAN_FACTOR)
											 )
						);
		
	}

	function moveWest() {

		recenter(
						 new point(
											 m_rctExtent.getCenter().x - (m_rctExtent.getWidth() * PAN_FACTOR), 
											 m_rctExtent.getCenter().y
											 )
						);
		
	}


	function moveNorthWest() {

		recenter(
						 new point(
											 m_rctExtent.getCenter().x - (m_rctExtent.getWidth() * PAN_FACTOR), 
											 m_rctExtent.getCenter().y + (m_rctExtent.getHeight() * PAN_FACTOR)
											 )
						);
		
	}
	
	function moveSouthWest() {

		recenter(
						 new point(
											 m_rctExtent.getCenter().x - (m_rctExtent.getWidth() * PAN_FACTOR), 
											 m_rctExtent.getCenter().y - (m_rctExtent.getHeight() * PAN_FACTOR)
											 )
						);
		
	}
	
	function moveNorthEast() {

		recenter(
						 new point(
											 m_rctExtent.getCenter().x + (m_rctExtent.getWidth() * PAN_FACTOR), 
											 m_rctExtent.getCenter().y + (m_rctExtent.getHeight() * PAN_FACTOR)
											 )
						);
		
	}

	function moveSouthEast() {

		recenter(
						 new point(
											 m_rctExtent.getCenter().x + (m_rctExtent.getWidth() * PAN_FACTOR), 
											 m_rctExtent.getCenter().y - (m_rctExtent.getHeight() * PAN_FACTOR)
											 )
						);
		
	}		

	function recenter(ptNewCenter) {
	//alert("Before : " + m_rctExtent.getWidth());
		m_rctExtent = new rect (
														ptNewCenter.x - (m_rctExtent.getWidth() / 2),
														ptNewCenter.y - (m_rctExtent.getHeight() / 2), 
														ptNewCenter.x + (m_rctExtent.getWidth() / 2),
														ptNewCenter.y + (m_rctExtent.getHeight() / 2)
													 );
	 //alert("After : " + m_rctExtent.getWidth());
	 //alert("Center = " + m_rctExtent.getLeft());
	}

	function zoom(scale) {
		m_rctExtent.scale(scale);
		m_iCurrentLevel = findLevel(m_rctExtent);		
	}

  // -----------------------------------------------
	// Category 2: Methods that perform map/page transformation.
  // -----------------------------------------------

	function isEventOverMap(eventX, eventY) {

		//alert("eventX = " + eventX + "eventY = " + eventY);
		if ((eventX <= (this.getTagLeft())) ||
        (eventY <= (this.getTagTop())) ||
				(eventX > (this.getTagWidth() + this.getTagLeft())) ||
				(eventY > (this.getTagHeight() + this.getTagTop()))) {
			return false;
		} else {
			return true;
		}

  }

	function toMapPoint(pageX, pageY) {

		var ptPixelsInTag = new point(pageX - m_iTagLeft, pageY - m_iTagTop);

		var dblX = m_rctExtent.getLeft() + ((ptPixelsInTag.x / m_iTagWidth) * (m_rctExtent.getWidth()));
		var dblY = m_rctExtent.getBottom() + (((m_iTagHeight - ptPixelsInTag.y) / m_iTagHeight) * (m_rctExtent.getHeight()));
		return (new point(dblX, dblY));

	}

	function toPagePoint(mapX, mapY) {

		var iX = ((mapX - m_rctExtent.getLeft()) / m_rctExtent.getWidth()) * m_iTagWidth;
		var iY = ((mapY - m_rctExtent.getBottom()) / m_rctExtent.getHeight()) * m_iTagHeight;

		return (new point((m_iTagLeft + iX), (m_iTagTop + (m_iTagHeight - iY))));

  }
  
  function handleOverviewClick (evt) {
	var img_x;
	var img_y;
	if (document.all) { // MSIE
	img_x = evt.offsetX;
	img_y = evt.offsetY;
	} else { // Netscape, etc.
	img_x = evt.clientX;
	img_y = evt.clientY;
	for (var offMark = evt.target; offMark;
	offMark = offMark.offsetParent) {
	img_x -= offMark.offsetLeft;
	}
	for (var offMark = evt.target; offMark;
	offMark = offMark.offsetParent) {
	img_y -= offMark.offsetTop;
	}
	}
	var coordinates = 'x: ' + img_x + ', y: ' + img_y;
	//alert (coordinates);
	var ptPixelsInTag = new point(img_x,img_y);
	var MapWidth = mapXMax - mapXMin;
	var MapHeight = mapYMax - mapYMin;
	//alert(MapWidth);
	//alert(MapHeight);
	var dblX = mapXMin + ((ptPixelsInTag.x / m_iOVWidth) * MapWidth);
	var dblY = mapYMin + (((m_iOVHeight - ptPixelsInTag.y) / m_iOVHeight) * MapHeight);
	//alert("dblX = " + dblX);
	//alert("dblY = " + dblY);
	recenter (new point(dblX, dblY));
	submit();
	}	

  // -----------------------------------------------
	// Category 3: Just plain properties.
  // -----------------------------------------------

	function getTagLeft() {
		return m_iTagLeft;
	}

	function getTagTop() {
		return m_iTagTop;
	}

	function getTagWidth() {
		return m_iTagWidth;
	}

	function getTagHeight() {	
		return m_iTagHeight;
	}

  // ------------------------------
  // ------ Private Functions -----
  // ------------------------------


function updateWidths()
{
	var i;
	for(i=0;i<m_arrWidths.length;i++);
	{
		m_arrWidths[i] = m_ExtentWidths[i];
		}
	
}

	function buildLevelRect(iLevel) {

		//var dblWidth = m_arrWidths[iLevel - 1];
		/*if ((iLevel < 1) && (iLevel >= 0.5))
			iLevel = iLevel - 0.2;
		else if ((iLevel < 0.5) && (iLevel > 0.3))
			iLevel = iLevel - 0.3;
		else if (iLevel <= 0.3 )
			iLevel = iLevel / 10;*/
		
		var dblWidth = (mapXMax - mapXMin) * iLevel

		return new rect(
										m_rctExtent.getCenter().x - (dblWidth / 2),
										m_rctExtent.getCenter().y, 
										m_rctExtent.getCenter().x + (dblWidth / 2), 
										m_rctExtent.getCenter().y
										);
	}
	
	function getLevelRect() {

	//var dblWidth = m_arrWidths[iLevel - 1];
	var lvl;
	//var dblWidth = (496444.6932705585 - 413526.4589320373)
	var dblWidth = (mapXMax - mapXMin)
	lvl = (m_rctExtent.getWidth() / dblWidth) * 100;
	return lvl;
	}

  function findLevel(rctExtent) {

		//alert("find level getleft = " + rctExtent.getLeft());
		var iNumLevels = m_arrWidths.length;
		var iLevel = 0;
		var wid = formatNumber(rctExtent.getWidth(),8);
		//alert("org is " + rctExtent.getWidth());
		for (i=0;i<iNumLevels;i++) {
			//alert(m_arrWidths[i]);	
			if (formatNumber(m_arrWidths[i],8) >= wid) {
				iLevel = i + 1;
				break;
			}
		}

		if (iLevel == 0) {
			iLevel = iNumLevels;
		}

		return iLevel;

	}

	function getAdjustedRect(rctExtent, iWidthPixels, iHeightPixels) {

		var dblExtentRatio;
		var dblMapRatio;

		var dblNewWidth;
		var dblNewHeight;
		var rctReturn;

		dblExtentRatio = rctExtent.getHeight() / rctExtent.getWidth();
		dblMapRatio = iHeightPixels / iWidthPixels;
		
		//alert("rctExtent.getHeight() = " + rctExtent.getHeight());
		//alert("rctExtent.getWidth() = " + rctExtent.getWidth());
		
		// -- adjust the width or height of the rectangle so its aspect ratio
		// -- matches that of the given dimensions
		
		//alert("dblExtentRatio = " + dblExtentRatio);
		//alert("dblMapRatio = " + dblMapRatio);
		
		if (dblExtentRatio > dblMapRatio) {
			rctReturn = makeRectFromCenter(rctExtent.getCenter(), (rctExtent.getHeight() / dblMapRatio), rctExtent.getHeight());
		} else {
	    rctReturn = makeRectFromCenter(rctExtent.getCenter(), rctExtent.getWidth(), (rctExtent.getWidth() * dblMapRatio));
		}

		return rctReturn;

	}

	function makeRectFromCenter(ptCenter, dblWidth, dblHeight) {

		var dblLeft, dblRight, dblBottom, dblTop;

		dblLeft = ptCenter.x - (dblWidth / 2);
		dblRight = ptCenter.x + (dblWidth / 2);
		dblBottom = ptCenter.y - (dblHeight / 2);
		dblTop = ptCenter.y + (dblHeight / 2);

		return new rect(dblLeft, dblBottom, dblRight, dblTop);

	}

}