var MAP_MAX_ZINDEX = 500;
var MAP_CONTROL_INDEX = 1000;
var MAP_DRAWING_INDEX = 900;
var MAP_POPUP_ZINDEX = 5000;

function objectClientPosition(obj) {
	var position = new Point(obj.offsetLeft, obj.offsetTop);
	var parent = obj.parentNode;

	while(parent && parent.tagName == 'DIV') {
		if(parent.offsetLeft) {
			position.x += parent.offsetLeft;
		}
		if(parent.offsetTop) {
			position.y += parent.offsetTop;
		}
		parent = parent.parentNode;
	}
	return position;
}

function GMap (EventManager) {
	var MySelf = this;
	var MapParent;
	var ImageParent = document.createElement('div');
	var ImageControl = document.createElement('input');
	var ImageImageMaps = document.createElement('map');
	var ScaleFactor = 1;
	var MapReference = null; 

	var CoordinateObject = null;
	var ScaleObject = null;
	
	ImageControl.type = 'Image';

	var ImageMapControl = document.createElement('img');
	ImageMapControl.src = BLANK_IMAGE;
	ImageMapControl.style.zIndex = MAP_CONTROL_INDEX - 1;

	ImageControl.src = BLANK_IMAGE;
	ImageControl.style.zIndex = MAP_CONTROL_INDEX;


	var ImageControlCanvas = document.createElement('canvas');
	ImageControlCanvas.style.zIndex = MAP_CONTROL_INDEX - 2;

	var FunctionOffset = new Point();
	var FunctionSemaphore = false;

	var DrawnPoints = new Array();
	var PreviousViews = new Array();
	var DrawBox;

	function refreshDrawBox() {
		DrawBox = document.createElement('div');
		DrawBox.style.position = 'absolute';
		DrawBox.style.border = 'solid 2px red';
		DrawBox.style.zIndex = MAP_DRAWING_INDEX;
		DrawBox.style.visibility = 'hidden';
		DrawBox.style.overflow = 'hidden';
		MapParent.appendChild(DrawBox);
	}

	var MapCenterPoint = new Point(576000, 157909.5);
	var MapScale = 25;


	var LayerURLs = new Array();
	var LayerLegends = new Array();
	var LayerImages = new Array();
	var LayerParameters = new Array();

	var min_z_index = MAP_MAX_ZINDEX;

	var VisibilityState = 'visible';
	function setVisibility(state) {
		for(var t in LayerImages) {
			LayerImages[t].style.visibility = state;
		}
		VisibilityState = state;
	}

	this.setVisibility = setVisibility;

	this.hideMap = function() {
		setVisibility('hidden');
	}

	this.showMap = function() {
		setVisibility('visible');
	}

	this.setCoordinateObject = function(obj) {
		CoordinateObject = obj;
	}

	this.setScaleObject = function(obj) {
		ScaleObject = obj;
	}


	this.setScaleFactor = function(scF) {
		ScaleFactor = scF;
	}
	
	this.setMapReference = function(m) {
		MapReference = m;
	}

	this.changePointScale = function(point,scale) {
		var circ = new Circle(point,scale);
		PreviousViews[PreviousViews.length] = circ;
		MapScale = scale;
		MapCenterPoint = point;
	}

	var LastActionTime = 0;

	this.setLastActionTime = function() {
		var d = new Date();
		LastActionTime = d.getTime();
		return LastActionTime;
	}

	this.getLastActionTime = function() {
		return LastActionTime;
	}


	/*
	 * This will refresh the map when a coordinate change happens
	 */
	var MapViewSet = false;
	this.onChangePointScale = function(psc) {
		if(MapReference && !REFERENCE_MAP_DYNAMIC && MapViewSet) {
			return true;
		}
		MapViewSet = true;
		MySelf.clearDrawingArea();
		PreviousViews[PreviousViews.length] = psc;
		MapScale = psc.Radius * ScaleFactor;
		MapCenterPoint = psc.Center;
		MySelf.refreshLayers();
		if(psc.Markup) {
			var ctx = ImageControlCanvas.getContext("2d");

			var mSize = MySelf.getMapSize();
			ctx.strokeStyle = "red";
			ctx.save();
				ctx.beginPath();
				ctx.moveTo(mSize.x/2,0);
				ctx.lineTo(mSize.x/2,mSize.y);
				ctx.stroke();
				ctx.moveTo(0, mSize.y/2);
				ctx.lineTo(mSize.x, mSize.y/2);
				ctx.stroke();
				ctx.closePath();
			ctx.restore();
/*			ctx.save();
				ctx.strokeStyle = "red";
				ctx.fillStyle = "red";
				ctx.arc(ZoomPoint.x, ZoomPoint.y, 3, 0, Math.PI * 2, true);
				ctx.fill();
				ctx.closePath();
			ctx.restore();*/

		}
	}

	/* Drawing Tools! */

	var DrawingShape = 'point';

	function startDrawing(event) {
		if(window.event) { event = window.event; event.which = event.button; }
		if(event.which != 1) { return false; }
		FunctionOffset = objectClientPosition(this);
		DrawnPoints = new Array();
		if(document.all) {	
			document.attachEvent("onmouseup", stopDrawing);
		} else {
			document.addEventListener("mouseup",stopDrawing,true);
		}
		if(DrawingShape == 'box' || DrawingShape=='evenbox' || DrawingShape=='scalebox') {
			DrawnPoints[0] = new Point(event.clientX-FunctionOffset.x, event.clientY-FunctionOffset.y);
		} else {
			MySelf.drawPoint(event.clientX-FunctionOffset.x, event.clientY-FunctionOffset.y);
		}
		FunctionSemaphore = true;
	}

	function whileDrawing(event) {
		if(window.event) { event = window.event; }
		if(FunctionSemaphore) {
			MySelf.drawPoint(event.clientX-FunctionOffset.x, event.clientY-FunctionOffset.y);
		}
	}

	function whileDrawingBox(event) {
		if(window.event) { event = window.event; }
		if(FunctionSemaphore) {
			DrawBox.style.visibility = 'visible';
			var currentPoint = new Point(event.clientX-FunctionOffset.x, event.clientY-FunctionOffset.y);
			var left = DrawnPoints[0].x - 2;
			var width = currentPoint.x - left;
			var top = DrawnPoints[0].y - 2;
			var height = currentPoint.y - top;

			var mSize = MySelf.getMapSize();
			var perspective = mSize.x / mSize.y;

			if(DrawingShape == 'evenbox') {
				perspective = 1;
			}

			if(DrawingShape =='scalebox' || DrawingShape == 'evenbox') {
				if(width > height) { width = Math.abs(height * perspective) * width / Math.abs(width); }
				else { height = Math.abs(width * 1/perspective) * height / Math.abs(height); }
			}

			if(width < 0) {
				left = left + width;
				width = Math.abs(width);
			}

			if(height < 0) {
				top = top + height;
				height = Math.abs(height);
			}
			/* These are here because they keep IE happy and FF doesn't care.
			 * I would love for someone to explain why this is necessary.
			 */
			width = width;
			height = height;

			DrawBox.style.top = top+'px';
			DrawBox.style.left = left+'px';
			DrawBox.style.height = height+'px';
			DrawBox.style.width = width+'px';
		}
	}
	function cancelDrawing() {
		if (document.all) {
			document.detachEvent("onmouseup",   stopDrawing);
		} else {
			document.removeEventListener("mouseup",   stopDrawing, true);
		}
		if(FunctionSemaphore) {
			FunctionSemaphore = false;
			DrawBox.style.visibility = 'hidden';
			DrawBox.style.left = '0px';
			DrawBox.style.top = '0px';
			DrawBox.style.height = '1px';
			DrawBox.style.width = '1px';
			for(var i = DrawnPoints.length; i >= 0; i--) {
				if(DrawnPoints[i] && DrawnPoints[i].parentNode) {
					var p = DrawnPoints[i].parentNode;
					p.removeChild(DrawnPoints[i]);
				}
			}
		}

	}
	function stopDrawing() {
		if (document.all) {
			document.detachEvent("onmouseup",   stopDrawing);
		} else {
			document.removeEventListener("mouseup",   stopDrawing, true);
		}

		if(FunctionSemaphore) {
			FunctionSemaphore = false;
			/* Convert Drawn Points into Ground Units */
			var GroundUnits = new Array();
			for(var i = 0; i < DrawnPoints.length; i++) {
				GroundUnits[i] = MySelf.pointToGroundUnits(new Point(DrawnPoints[i].offsetLeft,DrawnPoints[i].offsetTop));
			}
			EventManager.triggerEvent('finishdrawing', GroundUnits);
	/*		EventManager.triggerEvent('finishdrawing', DrawnPoints);*/
			DrawBox.style.visibility = 'hidden';
			DrawBox.style.left = '0px';
			DrawBox.style.top = '0px';
			DrawBox.style.height = '1px';
			DrawBox.style.width = '1px';
			for(var i = DrawnPoints.length; i >= 0; i--) {
				if(DrawnPoints[i] && DrawnPoints[i].parentNode) {
					var p = DrawnPoints[i].parentNode;
					p.removeChild(DrawnPoints[i]);
				}
			}
		}
	}

	this.mapStats = function() {
		logDebugMessage('Map Statistics', false, MapCenterPoint.toString(",")+' '+MapScale);
	}
	
	this.pointToGroundUnits = function(p) {
		MapCenterPoint.clean();
		p.x = (MapCenterPoint.x - (ImageControl.offsetWidth / 2 - p.x) * MapScale);
		p.y = (MapCenterPoint.y - (p.y - ImageControl.offsetHeight / 2) * MapScale);
		return p;
		
	}

	this.pointDrawTool = function(callFn) {
		this.loadDrawTool('poly', true);
	}

	var DrawingArea = new Array();

	this.polyDrawTool = function(shape, title) {
		this.loadDrawTool('poly',true);
		EventManager.addEventListener('finishdrawing', 'MapZoomTool', function () { 
			/* Ground Unit String is in WKT/GML Format */
			var groundUnitString = '';
			for(var i = 0; i < DrawnPoints.length; i++) {
				var p = new Point(DrawnPoints[i].offsetLeft,DrawnPoints[i].offsetTop);
				groundUnitString = groundUnitString + MySelf.pointToGroundUnits(p).toString(",") + ' ';
			}
			/* Close the polygon */
			if(shape == 'poly' || shape == 'circle') {
				groundUnitString = groundUnitString + MySelf.pointToGroundUnits(new Point(DrawnPoints[0].offsetLeft,DrawnPoints[0].offsetTop)).toString(",");
			}
			/*logDebugMessage('Points', false, groundUnitString);*/

			var pass = false;
			if(!title) {
				var msg = '';
				while(!pass) {
					title = prompt(msg+"Name for the object?", "Title");
					pass = true;
					if(LayerImages[title]) {
						pass = false;
						msg  = 'LAYER ALREADY EXISTS --';
					}
				}
				
			}

			if(title) {
				var bufferSize = prompt('Buffer Size?','0');
				if(!bufferSize) { bufferSize = 0; }
				
				/*var saveDrawingURL = '/mapscript/cgi-bin/saveDrawing.pl?coords=%COORDS%&shape=%SHAPE%&buffer=%BUFFER%&title=%TITLE%';*/
				var saveDrawingURL = DRAWING_URL;
				saveDrawingURL = saveDrawingURL.replace('%COORDS%', groundUnitString);
				saveDrawingURL = saveDrawingURL.replace('%SHAPE%', shape);
				saveDrawingURL = saveDrawingURL.replace('%BUFFER%', bufferSize);
				saveDrawingURL = saveDrawingURL.replace('%TITLE%', title);

				var DrawingMethod = 'GET';
				var DrawingPostInfo = true;
				if(saveDrawingURL.length > 1000) {
					DrawingMethod = 'POST';
					var saveDrawingArr = saveDrawingURL.split('?');
					saveDrawingURL = saveDrawingArr[0];
					DrawingPostInfo = saveDrawingArr[1];
				}

				var titleCopy = title;

				var saveDrawingControl = getHTTPObject();
				logDebugMessage('Drawing URL', false, saveDrawingURL);
				saveDrawingControl.open(DrawingMethod, saveDrawingURL, true);
				if(DrawingMethod == 'POST') {
					saveDrawingControl.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
				}


				saveDrawingControl.onreadystatechange = function() {
					if(saveDrawingControl.readyState == 4) {
						if(saveDrawingControl.responseXML) {
							loadDefaultsFromMapBook(saveDrawingControl.responseXML, null, EventManager);
							var selection = saveDrawingControl.responseXML.getElementsByTagName('selection');
							for(var s = 0; s < selection.length; s++) {
								DrawingArea[selection[s].getAttribute('title')] = selection[s].getAttribute('id');
							}

						}
					}
				}
				saveDrawingControl.send(DrawingPostInfo);
			}
			title = '';
		});

	}

	this.getDrawingAreas = function() {
		return DrawingArea;
	}

	this.resetDrawingArea = function() {
		MySelf.clearDrawingArea();
		DrawnPoints = new Array();
	}

	this.clearDrawingArea = function() {
	//	DrawnPoints = new Array();	
		refreshCanvas();
		ImageControlCanvas.getContext("2d").clearRect(0,0,1000,1000);
		EventManager.triggerEvent('measuredlength', 0);
	}

	function clearImageControlFn() {
		ImageControl.onmousedown = null;
		ImageControl.onmouseup = null;
		ImageControl.onmousemove = null;
		ImageControl.onclick = null;
		ImageControl.dblclick = null;
	}

	this.onChangeTool = function() {
		clearImageControlFn();
	}

	this.loadMeasureTool = function(mType) { // area or length
		if(mType == 'length') {
			MySelf.loadDrawTool('measureline',true);
			ImageControl._onclick = ImageControl.onclick;
			ImageControl.onclick = function (e) {
				if(window.event) { e = window.event; }
				ImageControl._onclick(e);

				var linesInGroundUnits = 0;
				for(var i = 1; i < DrawnPoints.length ; i++) {
					var gA = MySelf.pointToGroundUnits(new Point(DrawnPoints[i-1].x, DrawnPoints[i-1].y));
					var gB = MySelf.pointToGroundUnits(new Point(DrawnPoints[i].x, DrawnPoints[i].y));
						
					var gUnitSeg =new LineSegment(gA,gB);
					linesInGroundUnits += gUnitSeg.getLength();
				}
				EventManager.triggerEvent('measuredlength', linesInGroundUnits);
			}
		} else if(mType == 'area') {
			MySelf.loadDrawTool('measurearea',true);
			ImageControl._onclick = ImageControl.onclick;
			ImageControl.onclick = function (e) {
				if(window.event) { e = window.event; }
				ImageControl._onclick(e);
				var groundUnits = new Array();
				for(var i = 0; i < DrawnPoints.length ; i++) {
					var gA = MySelf.pointToGroundUnits(new Point(DrawnPoints[i].x, DrawnPoints[i].y));
					//var gA = new Point(DrawnPoints[i].x, DrawnPoints[i].y);
					groundUnits[i] = gA;
						
				}
				var poly = new Polygon();
				groundUnits[groundUnits.length] = new Point(groundUnits[0].x, groundUnits[0].y);
				poly.buildFromPoints(groundUnits);
				
				//alert(poly.area());	
				EventManager.triggerEvent('measuredlength', Math.abs(poly.area()));
			}
	
		} else {
			alert('Unknown Measurement Units!');
		}
	}

	this.setMapCursor = function(pCursor) {
		ImageControl.style.cursor = pCursor;
	}

	this.loadDrawTool = function(shape,override) {
		refreshDrawBox();
		ImageControl.style.zIndex = MAP_CONTROL_INDEX;
		ImageMapControl.style.zIndex = MAP_CONTROL_INDEX - 1;
		ImageControl.style.cursor = CURSOR_DRAW;

		if(!override) {
			EventManager.triggerEvent('changetool', 'Draw');
		}

		EventManager.addEventListener('changetool','MapDrawingTools', function () {
			EventManager.removeEventListener('changetool','MapDrawingTools');
			EventManager.removeEventListener('finishdrawing','MapZoomTool');
		});
		clearImageControlFn();
		DrawingShape = shape;
		if(shape == 'box' || shape == 'evenbox' || shape == 'scalebox') {
			ImageControl.onmousedown = startDrawing;
			ImageControl.onmousemove = whileDrawingBox;
			ImageControl.onmouseup = stopDrawing;
		} else if(shape == 'measureline') {
			ImageControl.style.cursor = CURSOR_MEASURE;
			DrawnPoints = new Array();
			MySelf.clearDrawingArea();
			ImageControl.onclick = function(event) {
				if(window.event) { event = window.event; }
				refreshCanvas();
				FunctionOffset = objectClientPosition(ImageControl);
				ZoomPoint.x = event.clientX - FunctionOffset.x;
				ZoomPoint.y = event.clientY - FunctionOffset.y;
				var ctx = ImageControlCanvas.getContext("2d");

				if(DrawnPoints.length <= 0) { ctx.beginPath(); }

				DrawnPoints[DrawnPoints.length] = new Point(ZoomPoint.x, ZoomPoint.y);
				if(DrawnPoints.length > 1) {
					var i = DrawnPoints.length-1;
					ctx.strokeStyle = "red";
					ctx.save();
						ctx.beginPath();
						ctx.moveTo(DrawnPoints[i-1].x, DrawnPoints[i-1].y);
						ctx.lineTo(DrawnPoints[i].x, DrawnPoints[i].y);
						ctx.stroke();
						ctx.closePath();
					ctx.restore();
				}
				ctx.save();
					ctx.strokeStyle = "red";
					ctx.fillStyle = "red";
					ctx.arc(ZoomPoint.x, ZoomPoint.y, 3, 0, Math.PI * 2, true);
					ctx.fill();
					ctx.closePath();
				ctx.restore();
			}

			ImageControl.ondblclick = function(event) {
			//	MySelf.clearDrawingArea();
				DrawnPoints = new Array();
			}
		} else if(shape == 'measurearea') {
			ImageControl.style.cursor = CURSOR_MEASURE;
			DrawnPoints = new Array();
			
			MySelf.clearDrawingArea();

			ImageControl.onclick = function(event) {
				if(window.event) { event = window.event; }
				refreshCanvas();
				FunctionOffset = objectClientPosition(ImageControl);
				ZoomPoint.x = event.clientX - FunctionOffset.x;
				ZoomPoint.y = event.clientY - FunctionOffset.y;
				var ctx = ImageControlCanvas.getContext("2d");

				if(DrawnPoints.length <= 0) { ctx.beginPath(); }

				DrawnPoints[DrawnPoints.length] = new Point(ZoomPoint.x, ZoomPoint.y);
				MySelf.clearDrawingArea();
				ctx.save();
					ctx.fillStyle = "rgba(0,200,0,.5)";
					ctx.beginPath();
					ctx.moveTo(DrawnPoints[0].x, DrawnPoints[0].y);
					for(var i = 1; i < DrawnPoints.length; i++) {
						ctx.lineTo(DrawnPoints[i].x,DrawnPoints[i].y);
					}
					ctx.closePath();
					ctx.fill();
				ctx.restore();

				ctx.save();
					ctx.strokeStyle = "red";
					ctx.lineWidth = 2;
					if(DrawnPoints.length == 1) {
						ctx.save();
						ctx.fillStyle = "red";
						ctx.beginPath();
							ctx.arc(DrawnPoints[0].x, DrawnPoints[0].y, 2,0,Math.PI*2,true);
							ctx.fill();
						ctx.closePath();
						ctx.restore();
					}
					ctx.beginPath();
					ctx.moveTo(DrawnPoints[0].x, DrawnPoints[0].y);

					for(var i = 1; i < DrawnPoints.length; i++) {
						ctx.lineTo(DrawnPoints[i].x,DrawnPoints[i].y);
					}
					ctx.closePath();
					ctx.stroke();

				ctx.restore();

			}

			ImageControl.ondblclick = function(event) {
			//	MySelf.clearDrawingArea();
				DrawnPoints = new Array();
			}

		} else {
			ImageControl.onmousedown = startDrawing;
			ImageControl.onmouseup = stopDrawing;
			ImageControl.onmousemove = whileDrawing;
		}
	}


	ImageControl.onmousedown = function() {
	}

	ImageControl.onmouseup = function(event) {
		if(window.event) { event = window.event; }
		}

	function zoomWheel(event) {
		if(window.event) { event = window.event; }
		var dir = 2;
		var delta = 0;
		if(event.wheelDelta) {
			delta = event.wheelDelta/120;
		} else if(event.detail) {
			delta = -event.detail/3;
		}
		if(delta > 0) {
			dir = .7;
		} else if (delta < 0) {
			dir = 1.5;
		}
		MySelf.zoomTo(ZoomPoint.x, ZoomPoint.y, dir);
	}

	/*
	 * Zooming Related Code
	 */

	function zoomTrackMouse(event) {
		if(window.event) { event = window.event; }
		FunctionOffset = objectClientPosition(ImageControl);
		ZoomPoint.x = event.clientX - FunctionOffset.x;
		ZoomPoint.y = event.clientY - FunctionOffset.y;
		if(CoordinateObject) {
			ZoomPoint.clean();
			var gUnit = MySelf.pointToGroundUnits(new Point(ZoomPoint.x, ZoomPoint.y));
/*			gUnit.x = round(gUnit.x, 2);
			gUnit.y = round(gUnit.y, 2);*/
			var llString = '';
			var sysArr = (new String(MAP_COORDINATE_SYSTEM)).split('-');
			if(window.toLatLong) {
				var unitConversion = new Point(gUnit.x, gUnit.y);
				unitConversion.x *= UNIT_CONVERSION[MAP_GROUND_UNITS]['M'];
				unitConversion.y *= UNIT_CONVERSION[MAP_GROUND_UNITS]['M'];
				var llPoint = window.toLatLong(sysArr[1], unitConversion);
				llPoint.x = round(llPoint.x,4);
				llPoint.y = round(llPoint.y,4);
				llString = ' Long, Lat: '+llPoint.toString(",");
			}
			CoordinateObject.innerHTML = 'X,Y: '+round(gUnit.x,2)+","+round(gUnit.y,2)+llString;

		}
	}

	var ZoomDirection = 1;
	var ZoomPoint = new Point();	
	function zoomToPoint(event) {
		if(window.event) { event = window.event; }
		FunctionOffset = objectClientPosition(ImageControl);
		//alert(FunctionOffset.toString(' '));
		MySelf.zoomTo(ZoomPoint.x, ZoomPoint.y, ZoomDirection);
	}
	
	if(document.all) {
		ImageControl.attachEvent('onmousemove', zoomTrackMouse);
	} else {
		ImageControl.addEventListener('mousemove', zoomTrackMouse, true);
	}

	this.loadZoomTool = function(v) {
		
		if(v == 1) { /* Pan */
			var PanPoint = new Point(0,0);

			ImageControl.style.cursor = CURSOR_ZOOM_PAN;
			ImageControl.onmousedown = function (e) {
				if(window.event) { e = window.event; e.which = e.button; }
				if(e.which != 1) { return false; }
				ImageControl.Origin = new Point(e.clientX, e.clientY);
				for(var l in LayerImages) {
					LayerImages[l].originalLeft = LayerImages[l].offsetLeft;
					LayerImages[l].originalTop = LayerImages[l].offsetTop;
				}
				PanPoint.x = 0;
				PanPoint.y = 0;
			}
			ImageControl.onmouseup = function (e) {
				if(window.event) { e = window.event; e.which = e.button; }
				if(e.which != 1) { return false; }
				MySelf.zoomTo(ImageControl.offsetWidth / 2 - PanPoint.x, ImageControl.offsetHeight / 2 - PanPoint.y, 1);
				/*delete ImageControl.Origin;*/
				ImageControl.Origin = null;
			}
			ImageControl.onmousemove = function (e) {
				if(window.event) { e = window.event; }
				//zoomTrackMouse(e);
				if(ImageControl.Origin) {
					for(var l in LayerImages) {
						LayerImages[l].style.left = LayerImages[l].originalLeft + (e.clientX - ImageControl.Origin.x) + 'px';
						LayerImages[l].style.top = LayerImages[l].originalTop + (e.clientY - ImageControl.Origin.y) + 'px';
					}
					PanPoint.x = e.clientX - ImageControl.Origin.x;
					PanPoint.y = e.clientY - ImageControl.Origin.y;
				}
				return false;
			}
			ImageControl.onkeypress = function (event) {
				if(window.event) { event = window.event; }
				var keyCode = getKeyCode(event);
				if(keyCode == 'CTRL+z') {
					ImageControl._onmouseup = ImageControl.onmouseup;
					ImageControl.onmouseup = function () {
						ImageControl.onmouseup = ImageControl._onmouseup;
					}
					ImageControl.Origin = null;
					for(var l in LayerImages) {
						LayerImages[l].style.left = LayerImages[l].originalLeft+'px';
						LayerImages[l].style.top = LayerImages[l].originalTop+'px';
					}
				}
			}
		} else if(v != 1) { /* Zoom In */
			MySelf.loadDrawTool(ZOOM_BOX_SHAPE,true);
			if(v < 1) {
				ImageControl.style.cursor = CURSOR_ZOOM_IN;
			} else {
				ImageControl.style.cursor = CURSOR_ZOOM_OUT;
			}
			ImageControl._onmousemove = ImageControl.onmousemove;
			ImageControl.onmousemove = function(event) {
				if(window.event) { event = window.event; }
				//zoomTrackMouse(event);
				this._onmousemove(event);
			}
			ImageControl.onkeypress = function (event) {
				if(window.event) { event = window.event; }
				var keyCode = getKeyCode(event);
				if(keyCode == 'CTRL+z') {

					cancelDrawing();	
				}
			}

			EventManager.addEventListener('finishdrawing', 'MapZoomTool', function () { 
				var Ratio = DrawBox.offsetWidth / ImageControl.offsetWidth;
				var hRatio = DrawBox.offsetHeight / ImageControl.offsetHeight;
				if(hRatio > Ratio) { Ratio = hRatio; }
				if(DrawBox.offsetWidth < 10) {
					var PanPoint = DrawnPoints[0];
					var shiftX = ImageControl.offsetWidth / 2 - PanPoint.x;
					var shiftY = ImageControl.offsetHeight / 2 - PanPoint.y;
					var oldW = ImageControl.offsetWidth;
					var oldH = ImageControl.offsetHeight;
					var newW = oldW * (1/v);
					var newH = oldH * (1/v);
					shiftX *= (1/v);
					shiftY *= (1/v);
					for(var l in LayerImages) {
						LayerImages[l].style.left = LayerImages[l].offsetLeft + shiftX - (newW - oldW) / 2 + 'px';
						LayerImages[l].style.top = LayerImages[l].offsetTop + shiftY - (newH - oldH) / 2 + 'px';
						LayerImages[l].style.width = newW + 'px';
						LayerImages[l].style.height = newH + 'px';
					}
					MySelf.zoomTo(0,0,1);
				} else {	
					var PanPoint = new Point(DrawBox.offsetLeft + DrawBox.offsetWidth / 2, DrawBox.offsetTop + DrawBox.offsetHeight / 2);
					if(v > 1) { v = 1 / Ratio; }
					else { v = Ratio; }
					var shiftX = ImageControl.offsetWidth / 2 - PanPoint.x;
					var shiftY = ImageControl.offsetHeight / 2 - PanPoint.y;
					var oldW = ImageControl.offsetWidth;
					var oldH = ImageControl.offsetHeight;
					var newW = oldW * (1/v);
					var newH = oldH * (1/v);
					shiftX *= (1/v);
					shiftY *= (1/v);
					for(var l in LayerImages) {
						LayerImages[l].style.left = LayerImages[l].offsetLeft + shiftX - (newW - oldW) / 2 + 'px';
						LayerImages[l].style.top = LayerImages[l].offsetTop + shiftY - (newH - oldH) / 2 + 'px';
						LayerImages[l].style.width = newW + 'px';
						LayerImages[l].style.height = newH + 'px';
					}
					MySelf.zoomTo(0,0,1);

				}
			});
			EventManager.addEventListener('changetool', 'MapZoomTool', function () {
				EventManager.removeEventListener('finishdrawing','MapZoomTool');
				EventManager.removeEventListener('changetool', 'MapZoomTool');
			});
		}

		ImageControl.style.zIndex = MAP_CONTROL_INDEX;
		ImageMapControl.style.zIndex = MAP_CONTROL_INDEX - 1;
		if(document.all) {
			ImageControl.onmousewheel = zoomWheel;
		} else {
			ImageControl.addEventListener('DOMMouseScroll', zoomWheel, false);
		}
		ZoomDirection = v;
	}
	


	this.clearLayerParams = function(mapTitle) {
		LayerParameters[mapTitle] = new Array();
	}

	this.addLayerParam = function(mapTitle,paramName,paramValue) {
		if(!LayerParameters[mapTitle]) { LayerParameters[mapTitle] = new Array(); }
		if(!LayerParameters[mapTitle][paramName]) {
			LayerParameters[mapTitle][paramName] = new Array();
		}
		LayerParameters[mapTitle][paramName].push(paramValue);
	}

	this.getLayerParamString = function(mapTitle) {
		if(!LayerParameters[mapTitle]) { return false; }
		var urlString = '';
		for(var p in LayerParameters[mapTitle]) {
			if(LayerParameters[mapTitle][p]) {
				for(var i = 0; i < LayerParameters[mapTitle][p].length; i++) {
					urlString += p+'='+LayerParameters[mapTitle][p][i]+'&';
				}
			}
		}
		urlString = urlString.substring(0,urlString.length - 1);
		return urlString;
	}

	this.addLayer = function (mapXMLObj) {
		var mapFile = mapXMLObj.getElementsByTagName('file')[0].firstChild.nodeValue;
		var mapTitle = mapXMLObj.getAttribute('title');
		var mapOpacity = mapXMLObj.getAttribute('opacity');

		mapFile = trim(mapFile);
		LayerURLs[mapTitle] = mapFile;/*+'?mode=map&mapext=%EXTENTS%&mapsize=%SIZE%';*/

		if(!LayerImages[mapTitle]) {
			LayerImages[mapTitle] = document.createElement('img');
			LayerImages[mapTitle].style.position = 'absolute';
			LayerImages[mapTitle].id = 'LayerImage-'+mapTitle;
		}
		if(mapOpacity) {
			setOpacity(LayerImages[mapTitle], mapOpacity);
		}
		

		var zIndex = mapXMLObj.getAttribute('zindex');
		if(!zIndex || zIndex > 0) {
			LayerImages[mapTitle].style.zIndex = MAP_MAX_ZINDEX;
			for(var title in LayerImages) {
				LayerImages[title].style.zIndex = parseInt(LayerImages[title].style.zIndex)-1;
			}
			min_z_index--;
		} else {
			min_z_index--;
			LayerImages[mapTitle].style.zIndex = min_z_index;
		}
		ImageParent.appendChild(LayerImages[mapTitle]);
		MySelf.autoFitLayer(mapTitle);
		LayerImages[mapTitle].onload = function() {
			this.isLoaded = true;
			var allVisible = true;
			MySelf.autoFitLayer(mapTitle);
			for(var l in LayerImages) {
				LayerImages[l].style.visibility = 'hidden';
				if(!LayerImages[l].isLoaded) {
					allVisible = false;
				}
			}
			if(allVisible) {
				for(var l in LayerImages) {
					LayerImages[l].style.visibility = VisibilityState;
				}
			}
			EventManager.triggerEvent('imagelayer', mapTitle);
		}

		MySelf.clearLayerParams(mapTitle);
		var mapParams = mapXMLObj.getElementsByTagName('param');
		for(var i = 0; i < mapParams.length; i++) {
			MySelf.addLayerParam(mapTitle, mapParams[i].getAttribute('name'), mapParams[i].getAttribute('value'));
		}
		/*
		 * Custom Legend settings
		 */
		if(mapXMLObj.getElementsByTagName('legend')[0] && mapXMLObj.getElementsByTagName('legend')[0].firstChild.nodeValue) {
			LayerLegends[mapTitle] = mapXMLObj.getElementsByTagName('legend')[0].firstChild.nodeValue;
		}
		Events.triggerEvent('refreshlayer', mapTitle);
	}

	this.confirmRemoveLayer = function(mapTitle) {
		MySelf.removeLayer(mapTitle);
	}

	this.removeLayer = function(mapTitle) {
		var imageMap = document.getElementById('ImageMap-'+mapTitle);
		if(imageMap) {
			var areas = imageMap.getElementsByTagName('area');
			for(var a = areas.length - 1; a >= 0; a--) {
				var p = areas[a].popup[0].parentNode;
				for(var pop = 0; pop < areas[a].popup.length; pop++) {
					p.removeChild(areas[a].popup[pop]);
				}
				imageMap.removeChild(areas[a]);
			}
			var p = imageMap.parentNode;
			p.removeChild(imageMap);
		}
		var p = LayerImages[mapTitle].parentNode;
		p.removeChild(LayerImages[mapTitle]);
		delete LayerImages[mapTitle];
		delete LayerURLs[mapTitle];
		if(DrawingArea[mapTitle]) {
			delete DrawingArea[mapTitle];
		}
	}

	this.getLayerURLs = function() {
		var zOrdered = MySelf.getLayersByZIndex();
		var urls = new Array();
		for(var i = 0; i < zOrdered.length; i++) {
			urls[zOrdered[i]] = LayerURLs[zOrdered[i]];
		}
		return urls;
	}

	this.getLayerTitles = function() {
		var layers = new Array();
		for(var title in LayerImages) {
			layers[layers.length] = title;
		}
		return layers;
	}

	this.getLayersByZIndex = function() {
		var orderedLayers = new Array();
		for(var title in LayerImages) {
			orderedLayers[orderedLayers.length] = title;
		}
		for(var i = 0; i < orderedLayers.length; i++) {
			for(var  j = i; j < orderedLayers.length; j++) {
				var iImage = LayerImages[orderedLayers[i]];
				var jImage = LayerImages[orderedLayers[j]];
				if(parseInt(iImage.style.zIndex) < parseInt(jImage.style.zIndex)) {
					var temp = orderedLayers[i];
					orderedLayers[i] = orderedLayers[j];
					orderedLayers[j] = temp;
				}
			}
		}
		return orderedLayers;
	}

	this.showOrderedLayers = function() {
		var str = '';
		var layers = this.getLayersByZIndex();
		for(var i = 0; i < layers.length; i++) {
			str = str+layers[i]+'('+LayerImages[layers[i]].style.zIndex+'),';
		}
	}
	
	this.shiftLayer = function(mapTitle, direction) {
		var orderedLayers = this.getLayersByZIndex();
		var selectedLayerIndex = -1;
		
		for(var i = 0; i < orderedLayers.length && selectedLayerIndex < 0; i++) {
			if(orderedLayers[i] == mapTitle) {
				selectedLayerIndex = i;
			}
		}
		if(selectedLayerIndex >= 0) {
			var baseImage = LayerImages[mapTitle];
			var targetImage = null; 
			/* Move the layer up, if it's not at the top*/
			if(direction > 0 && selectedLayerIndex > 0) {
				targetImage = LayerImages[orderedLayers[selectedLayerIndex-1]];
			/* Move the layer down, if it's not at the bottom */
			} else if(direction < 0 && selectedLayerIndex < orderedLayers.length - 1) {
				targetImage = LayerImages[orderedLayers[selectedLayerIndex+1]];
			}
			if(targetImage) {
				var tempIndex = baseImage.style.zIndex;
				baseImage.style.zIndex = targetImage.style.zIndex;
				targetImage.style.zIndex = tempIndex;
			}
		}
	}

	var REFRESH_LOCKOUT = false;

	this.zoomToScaledImage = function() {
		var orderedLayers = MySelf.getLayersByZIndex();
		/* zoomLayer will be Scaled to whatever the new image should be */
		var zoomLayer = LayerImages[orderedLayers[0]];
		var imageTop = zoomLayer.offsetTop;
		var imageLeft = zoomLayer.offsetLeft;

		var imageWidth = zoomLayer.offsetWidth;
		var imageHeight = zoomLayer.offsetHeight;

		/* ImageControl never changes size */
		var viewportTop = ImageControl.offsetTop;
		var viewportLeft = ImageControl.offsetLeft;
		var viewportWidth = ImageControl.offsetWidth;
		var viewportHeight = ImageControl.offsetHeight;

		/* Scale Change between the two images */
		var scale = viewportWidth / imageWidth * MapScale; 
		
		var groundTop = MapCenterPoint.y - MapScale * viewportHeight / 2;
		var groundLeft = MapCenterPoint.x - MapScale * viewportWidth / 2;

		/* Find the new Centerpoint in Pixel Space */
		var viewportMidX = (viewportLeft - imageLeft) + viewportWidth / 2;
		var viewportMidY = (viewportTop - imageTop) + viewportHeight / 2;
		var imagePercentX = viewportMidX / imageWidth;
		var imagePercentY = 1 - (viewportMidY / imageHeight);	

		var unscaledImageX = imagePercentX*viewportWidth;
		var unscaledImageY = imagePercentY*viewportHeight;

		/* Convert to ground units */
		var groundCenterX = groundLeft + unscaledImageX * MapScale;
		var groundCenterY = groundTop + unscaledImageY * MapScale; 
		EventManager.changePointScale(new Point(groundCenterX, groundCenterY), scale / ScaleFactor);
	}

	this.zoomToViewString = function(str) {
		var psC = convertViewString(str,MySelf.getMapSize());
		EventManager.changePointScale(psC.Center, psC.Radius);
	}
	
	this.zoomTo = function(x,y,direction) {
		if(REFRESH_LOCKOUT) return false;

		var orderedLayers = MySelf.getLayersByZIndex();
		var zoomLayer = LayerImages[orderedLayers[0]];
		var imgW = zoomLayer.offsetWidth;
		var imgH = zoomLayer.offsetHeight;

		var mapSize = MySelf.getMapSize();
		var diffY = ImageControl.offsetTop - zoomLayer.offsetTop;
		var diffX = ImageControl.offsetLeft - zoomLayer.offsetLeft;
		
		var PointImageX = diffX + x;
		var PointImageY = diffY + y;

		var wPercent = PointImageX / imgW;
		var hPercent = PointImageY / imgH;
		// Do some zooming tricks
		var imgSizeFactor = 1 / direction; // Inverse of the scale change
		var newW = imgSizeFactor * imgW;
		var newH = imgSizeFactor * imgH;

		var xLoc = x-(mapSize.x / 2);
		var yLoc = ((mapSize.y / 2) - y);
		var wRatio = newW / ImageControl.offsetWidth;
		var hRatio = newH / ImageControl.offsetHeight;
		if(hRatio > wRatio) { wRatio = hRatio; }

		var newScale = MapScale * wRatio;

		if(newScale < .01) {
			return false;
		}
				
		if(direction != 1) {
			for(var layer in LayerImages) {
				var img = LayerImages[layer];
				//img.style.visibility = 'hidden';
				img.style.width = newW + 'px';
				img.style.height = newH + 'px';
				img.style.left = (newW * wPercent * -1 +  x)+'px';
				img.style.top = (newH * hPercent * -1 +  y)+'px';
				//img.style.visibility = 'visible';
			}
		}

		

		window.triggerMapRefresh = function(time) {
			REFRESH_LOCKOUT = true;
			if(time == LastActionTime) {
				MySelf.zoomToScaledImage();
				LastActionTime = 0;
			}
			REFRESH_LOCKOUT = false;
		}
		LastActionTime ++;
		setTimeout("window.triggerMapRefresh("+LastActionTime+")", 1000);
	}

		
	this.drawPoint = function(x,y) {
		var lastPoint = DrawnPoints[DrawnPoints.length-1];
		if(lastPoint) {
			var distx = (lastPoint.offsetLeft - x);
			var disty = (lastPoint.offsetTop - y);
			
			var dist = distx*distx + disty*disty;
			if(dist < 100) {
				return false;
			}
		}

		var newPoint = document.createElement('div');
		newPoint.style.position = 'absolute';
		newPoint.style.background = 'red';
		newPoint.style.border = 'none';
		newPoint.style.overflow = 'hidden';
		newPoint.style.width = '5px';
		newPoint.style.height = '5px';
		newPoint.style.left = x+'px';
		newPoint.style.top = y+'px';
		newPoint.className = 'DrawnPoint';
		DrawnPoints[DrawnPoints.length] = newPoint;
		ImageParent.appendChild(newPoint);
	}

	this.getMapSize = function() {
		var SizeObject = ImageControl;
		if(!SizeObject.offsetWidth) {
			SizeObject = MapParent;
		}
		var point = new Point(SizeObject.offsetWidth, SizeObject.offsetHeight);
		return point;
	}

	this.setParent = function(p) {
		MapParent = p;
		ImageParent.style.position = 'absolute';
		ImageParent.style.left = '0px';
		ImageParent.style.top = '0px';

		ImageControl.style.position = 'absolute';
		ImageControl.style.border = 'none';
		ImageControl.style.left = '0px';
		ImageControl.style.top = '0px';

		ImageMapControl.style.position = 'absolute';
		ImageMapControl.style.border = 'none';
		ImageMapControl.style.left = '0px';
		ImageMapControl.style.top = '0px';

		ImageControlCanvas.style.position = 'absolute';
		ImageControlCanvas.style.border = 'none';
		ImageControlCanvas.style.left = '0px';
		ImageControlCanvas.style.top = '0px';


		MapParent.appendChild(ImageParent);
		MapParent.appendChild(ImageControl);
		MapParent.appendChild(ImageMapControl);
		MapParent.appendChild(ImageControlCanvas);

		//MapParent.appendChild(DrawBox);
		refreshDrawBox();
		MapParent.style.overflow = 'hidden';

		this.autoFitLayers();	
	}


	this.processURL = function(url, extents, mSize, mapfile) {
		url = url.replace("%EXTENTS%",extents);
		var extentsArr = extents.split(' ');
		url = url.replace("%MINX%", extentsArr[0]);
		url = url.replace("%MINY%", extentsArr[1]);
		url = url.replace("%MAXX%", extentsArr[2]);
		url = url.replace("%MAXY%", extentsArr[3]);
		url = url.replace("%SIZE%", mSize.toString(" "));
		url = url.replace("%WIDTH%", mSize.x);
		url = url.replace("%HEIGHT%", mSize.y);
		url = url.replace("%MAPBOOK%", MAPBOOK_FILE);
		url = url.replace("%MAPFILE%", mapfile);
		return url;

	}

	this.preprocessURL = function(type, mapTitle) {
		var layerURL = MAPSERVER_IMAGE_URL;
		if(type == 'legend') {
			layerURL = MAPSERVER_LEGEND_URL;
		} else if(type == 'data') {
			layerURL = MAPSERVER_DATA_URL;
		}

		if(LayerURLs[mapTitle].match(/http/i)) {
			layerURL = LayerURLs[mapTitle];
		} else {
			layerURL = layerURL.replace('%MAPFILE%', LayerURLs[mapTitle]);
		}
		var parameters = MySelf.getLayerParamString(mapTitle);
		if(!parameters) { parameters = ''; }

		return layerURL + '&' + parameters;
	}

	this.getExtent = function (delim) {
		var mapSize = MySelf.getMapSize();
		var gisOffsetW = mapSize.x / 2 * MapScale;
		var gisOffsetH = mapSize.y / 2 * MapScale;
		MapCenterPoint.clean();
		var minPoint = new Point(MapCenterPoint.x - gisOffsetW, MapCenterPoint.y - gisOffsetH);
		var maxPoint = new Point(MapCenterPoint.x + gisOffsetW, MapCenterPoint.y + gisOffsetH);
		var MapCoords = new LineSegment(minPoint,maxPoint);

		var mSize = this.getMapSize();

		var extent = MapCoords.toString(delim);
		return extent;
	}

	this.refreshLayer = function(mapTitles) {
		var mapSize = MySelf.getMapSize();
		
		var mSize = this.getMapSize();

		var extent = this.getExtent(" ");
		var size = this.getMapSize().toString(" ");

		for(var i = 0; i < mapTitles.length; i++) {
			if(!LayerURLs[mapTitles[i]]) {
				break;
			}

			/*
			 * Do a little clean up on the Layer Image Maps 
			 */
			var imageMap = document.getElementById('ImageMap-'+mapTitles[i]);
			if(imageMap) {
				var areas = imageMap.getElementsByTagName('area');
				for(var a = areas.length - 1; a >= 0; a--) {
					var p = areas[a].popup[0].parentNode;
					for(var pop = 0; pop < areas[a].popup.length; pop++) {
						p.removeChild(areas[a].popup[pop]);
					}
					imageMap.removeChild(areas[a]);
				}
			}

			
			var imageURL = MAPSERVER_IMAGE_URL;
			if(LayerURLs[mapTitles[i]].match(/http/i)) {
				imageURL = LayerURLs[mapTitles[i]];
			}
			imageURL = this.processURL(imageURL, extent, mSize, LayerURLs[mapTitles[i]]);
			var parameters = MySelf.getLayerParamString(mapTitles[i]);
			LayerImages[mapTitles[i]].src = imageURL+'&'+parameters;
			logDebugMessage('Image URL', false, imageURL);

			if(!LayerURLs[mapTitles[i]].match(/http/i)) {
				var dataURL = MAPSERVER_DATA_URL;
				dataURL = this.processURL(dataURL, extent, mSize, LayerURLs[mapTitles[i]]);
				if(parameters) {
					dataURL = dataURL + '&' + parameters;
				}
				this.loadData(mapTitles[i], dataURL);
				logDebugMessage('Data URL', false, dataURL);
			}

			if(!LayerURLs[mapTitles[i]].match(/http/i) || LayerLegends[mapTitles[i]]) {
				var legendURL = MAPSERVER_LEGEND_URL;
				if(LayerLegends[mapTitles[i]]) {
					legendURL = LayerLegends[mapTitles[i]];
				}
				legendURL = this.processURL(legendURL, extent, mSize, LayerURLs[mapTitles[i]]);
				if(parameters) {
					legendURL = legendURL + '&' + parameters;
				}
				
				var obj = document.createElement('layer');
				obj.setAttribute('legend', legendURL);
				obj.setAttribute('id',mapTitles[i]);
				EventManager.triggerEvent('legendlayer', obj);

				logDebugMessage('Legend URL', false, legendURL);
			}
		}

	}

	var Popups = new Array();
	this.getPopupData = function(i) {
		return Popups[i];
	}

	this.getPointScale = function() {
		return new Circle(MapCenterPoint, MapScale);
	}
	
	this.clearPopups = function() {
		var p = MapParent; //ImageControl.parentNode;
		var d = p.getElementsByTagName('div');
		for(var i = 0; i < d.length; i++) {
			if(d[i].className == 'Popup') {
				d[i].style.visibility = 'hidden';
			}
		}
	}

	this.loadData = function(id, dataCall) {
		var http = getHTTPObject();
		/*var xmlhttp = getHTTPObject();
		xmlhttp.open('HEAD', dataCall, true);
		xmlhttp.onreadystatechange = function() {
			if(xmlhttp.readyState == 4) {
				if(xmlhttp.status == 200) {
					//alert(xmlhttp.getAllResponseHeaders());
				} else {
					return false;
				}
			}
		}
		xmlhttp.send(null);*/

		http.open('GET', dataCall, true);
		http.onreadystatechange = function() {
			if(http.readyState == 4) {
				if(http.responseXML) {
					var imageMap = document.createElement('map');
					var imageMapName = 'ImageMap-'+id;
					imageMap.id = imageMapName;
					if(document.all) {
						imageMap = document.createElement('<map name="'+imageMapName+'">');
					} else {
						imageMap.name = imageMapName;
					}
					var imageMapTest = document.getElementById(imageMapName);

					imageMap.className = 'ImageMaps';
					if(imageMapTest) { imageMap = imageMapTest; }
					var popups = http.responseXML.getElementsByTagName('popup');
					var popups = http.responseXML.getElementsByTagName('popup');
					var offsetPoint = objectClientPosition(ImageControl);

					var styleObject = http.responseXML.getElementsByTagName('style')[0];
					var contentsFunction = function () { };
					var titleFunction = function () { };
					
					if(styleObject) {
						contentsFunction = getStyleFunction('contents', styleObject);
						titleFunction = getStyleFunction('title', styleObject);
					}
					var xCoord = new Array();
					var yCoord = new Array();
					var allShapes = new Array();

					var bin = new Array();
					for(var i = 0; i < popups.length; i++) {
						var coords = popups[i].getAttribute('coords');
							var coordsArr = coords.split(',');
							var found = false;

							for(var x in xCoord) {
								var w = Math.pow(xCoord[x] - coordsArr[0],2);
								var h = Math.pow(yCoord[x] - coordsArr[1],2);
								if(w+h < 49) {
									found = true;
									bin[x][bin[x].length] = popups[i];
								}
							}
							if(!found) {
								xCoord[coords] = coordsArr[0];
								yCoord[coords] = coordsArr[1];
								bin[coords] = new Array();
								bin[coords][0] = popups[i];
								allShapes[coords] = popups[i].getAttribute('shape');
							}

					}

					for(var b in bin) {
						var area = document.createElement('area');
						area.shape = allShapes[b];
						area.coords = b;

						area.popup = new Array();
						for(var i = 0; i < bin[b].length; i++) {
							var myPopup = document.createElement('div');
							myPopup.className = 'Popup';
							var myPopupTitle = document.createElement('div');
							myPopupTitle.appendChild(document.createTextNode(bin[b][i].getElementsByTagName('title')[0].firstChild.nodeValue));

							myPopup.appendChild(myPopupTitle);

							myPopup.draggable = new Draggable(myPopup, myPopupTitle, true,true,true);

							titleFunction(myPopupTitle);
							contentsFunction(myPopup);
							var items = bin[b][i].getElementsByTagName('item');

							for(var item = 0; item < items.length; item++) {
								var title = items[item].getAttribute('title');
								var val = '';
								if(items[item].firstChild) {
									val = items[item].firstChild.nodeValue;
								}
								var titleObj = document.createElement('span');
								titleObj.style.fontWeight = 'bold';
								var valObj = document.createElement('span');
								if(title) {
									titleObj.appendChild(document.createTextNode(title));
								}
								if(items[item].getAttribute('href')) {
									var link = document.createElement('a');
									link.href = items[item].getAttribute('href');
									var tgt = items[item].getAttribute('target');
									if(!tgt) { tgt = '_blank'; }
									link.setAttribute('target',tgt);
									link.innerHTML = val;
									valObj.appendChild(link);
								} else {
									valObj.innerHTML = val;
								}
								myPopup.appendChild(titleObj);
								myPopup.appendChild(valObj);
								myPopup.appendChild(document.createElement('br'));
							}

							var closeL = document.createElement('a');
							var closeImg = document.createElement('img');
							closeImg.src = REMOVE_ICON;
							closeL.appendChild(closeImg);
							closeL.style.position = 'absolute';
							closeL.style.right = '0px';
							closeL.style.top = '0px';
							closeImg.style.width = '8px';
							closeImg.style.height = '8px';

							closeL.onclick = function () {
								this.parentNode.style.visibility = 'hidden';
								this.area.onmouseup();
							}
							myPopup.appendChild(closeL);
							ImageControl.parentNode.appendChild(myPopup);
							area.popup[area.popup.length] = myPopup;
							closeL.area = area;
						}
						area.popupMove = true;
						area.onmousemove = function (event) {  
							if(window.event) { event = window.event; }
							if(!this.popupMove) { return false; }
							var mouseY = event.clientY-offsetPoint.y;
							var mouseX = event.clientX-offsetPoint.x;
							var offsetX = 4;
							var offsetY = 4;
							for(var i = 0; i < this.popup.length; i++) {
								this.popup[i].style.zIndex =  MAP_POPUP_ZINDEX;
								/*if(mouseY + this.popup[i].offsetHeight < ImageControl.offsetHeight) {*/
								if(mouseY < ImageControl.offsetHeight / 2) {
									this.popup[i].style.top = mouseY+offsetY+'px';
									this.popup[i].style.bottom = 'auto';
								} else {
									this.popup[i].style.bottom = (ImageControl.offsetHeight - mouseY)+offsetY+'px';
									this.popup[i].style.top = 'auto';
								}
								/*if(mouseX + this.popup[i].offsetWidth < ImageControl.offsetWidth) {*/
								if(mouseX < ImageControl.offsetWidth /2 ) {
									this.popup[i].style.left = mouseX+offsetX+'px';
									this.popup[i].style.right = 'auto';
								} else {
									this.popup[i].style.right = (ImageControl.offsetWidth - mouseX)+offsetX+'px';
									this.popup[i].style.left = 'auto';
								}

								this.popup[i].style.visibility = 'visible';
								offsetY += 10;
								offsetX += 10;
							}
						}
						area.onmouseup = function () {
							if(this.onmouseout) {
								this._onmouseout = this.onmouseout;
								this.onmouseout = null;
								this.popupMove = false;
							} else {
								this.onmouseout = this._onmouseout;
								this._onmouseout = null;
								this.popupMove = true;
							}
						}
		
						area.onmouseout = function (event) {
							for(var i = 0; i < this.popup.length; i++) {
								this.popup[i].style.visibility = 'hidden';
							}
						}
						imageMap.appendChild(area);
					}
					if(!imageMapTest) {
						document.getElementsByTagName('body')[0].appendChild(imageMap);
					}
					if(popups.length > 0) {
						EventManager.triggerEvent('datalayer',id);
					}
				}
			}
		}
		http.send(true);
	}

	this.activateLayer = function(mapTitle) {
		var imageMapName = 'ImageMap-'+mapTitle;
		ImageMapControl.setAttribute('usemap', '#'+imageMapName);
		ImageMapControl.setAttribute('useMap', '#'+imageMapName);
		ImageMapControl.ismap = true;
		ImageMapControl.style.zIndex = MAP_CONTROL_INDEX;
		ImageControl.style.zIndex = MAP_CONTROL_INDEX - 1;
		ImageControlCanvas.style.zIndex = MAP_CONTROL_INDEX - 2;
	}

	function refreshCanvas() {
			ImageControlCanvas = MapParent.getElementsByTagName('canvas')[0];
			ImageControlCanvas.style.zIndex = MAP_CONTROL_INDEX - 2;
			ImageControlCanvas.style.position = 'absolute';
			ImageControlCanvas.style.top = '0px';
			ImageControlCanvas.style.left = '0px';
	}



	this.autoFitLayers = function() {
		var mapSize = new Point(MapParent.offsetWidth, MapParent.offsetHeight);
		ImageParent.style.width = mapSize.x+'px';
		ImageParent.style.height = mapSize.y+'px';
		for(var title in LayerImages) {
			MySelf.autoFitLayer(title);
		}
		ImageControl.style.width = mapSize.x+'px';
		ImageControl.style.height = mapSize.y+'px';
		ImageMapControl.style.width = mapSize.x+'px';
		ImageMapControl.style.height = mapSize.y+'px';
		refreshCanvas();
		ImageControlCanvas.width = mapSize.x;
		ImageControlCanvas.height = mapSize.y;
		if(document.all) {
			ImageControlCanvas.style.width = mapSize.x+'px';
			ImageControlCanvas.style.height = mapSize.y+'px';
		}
	}

	this.autoFitLayer = function(mapTitle) {
		var mapSize = this.getMapSize();
		this.resizeLayer(mapTitle,mapSize.x,mapSize.y);
	}

	this.resizeLayer = function(mapTitle,w,h) {
		//LayerImages[mapTitle].style.visibility = 'hidden';
		LayerImages[mapTitle].style.top = '0px';
		LayerImages[mapTitle].style.left = '0px';
		LayerImages[mapTitle].style.width = w+'px';
		LayerImages[mapTitle].style.height = h+'px';
		//LayerImages[mapTitle].style.visibility = 'visible';
	}

	this.reloadLayers = function() {
		MySelf.autoFitLayers();
		MySelf.refreshLayers();
	}

	var ReferenceIndicator = null;
	
	this.refreshLayers = function() {
		if(MapReference) {
			var oldMap = MapReference.getMapSize();
			var newW = oldMap.x / ScaleFactor;
			var newH = oldMap.y / ScaleFactor;
			var MySize = MySelf.getMapSize();
			var left = (MySize.x - newW) / 2;
			var top = (MySize.y - newH) / 2;
			if(!ReferenceIndicator) { 
				ReferenceIndicator = document.createElement('div');
				ReferenceIndicator.gDRAGGER = new Draggable(ReferenceIndicator, ReferenceIndicator, true, true, true);
				ImageControl._onmousedown = ImageControl.onmousedown;
				ImageControl.onmousedown = function (event) {
					if(window.event) { event = window.event; event.which = event.button; }
					if(event.which > 1) {
						// If you right click, hide the reference map box for better zooming.
						//ReferenceIndicator.style.visibility = 'hidden';
						event.returnValue = false;
						if(ReferenceIndicator.style.zIndex < MAP_CONTROL_INDEX) {
							ReferenceIndicator.style.zIndex = MAP_CONTROL_INDEX + 1;
						} else {
							ReferenceIndicator.style.zIndex = MAP_CONTROL_INDEX - 1;
						}
						var currentBg = ReferenceIndicator.style.background;
						ReferenceIndicator.style.background = ReferenceIndicator.swapBG;
						ReferenceIndicator.swapBG = currentBg;

						var currentBorder = ReferenceIndicator.style.border;
						ReferenceIndicator.style.border = ReferenceIndicator.swapBorder;
						ReferenceIndicator.swapBorder = currentBorder;
					} else {
						this._onmousedown(event);
					}
					if(event.preventDefault) {
						event.preventDefault();
					}
					return false;
				}
				ImageControl.oncontextmenu = function (event) {
					if(window.event) { event = window.event; }
					event.returnValue = false;
					if(event.preventDefault) {
						event.preventDefault();
					}
					return false;
				}
				ReferenceIndicator.oncontextmenu = ImageControl.oncontextmenu;

				ReferenceIndicator.old_onmousedown = ReferenceIndicator.onmousedown;
				ReferenceIndicator.onmousedown = function(event) {
					if(window.event) { event = window.event; event.which = event.button; }
					if(event.which > 1) {
						ImageControl.onmousedown(event);
						// Quit passing things through!
						event.returnValue = false;
						if(event.preventDefault) {
							event.preventDefault();
						}
						return false;
					} else {
						ReferenceIndicator.old_onmousedown(event);
					}	
				}

				ReferenceIndicator.gDRAGGER.onDrop = function (trig,obj) {
					var diffX = trig.offsetLeft - left;
					var diffY = trig.offsetTop - top;
					for(var l in LayerImages) {
						LayerImages[l].style.left = LayerImages[l].offsetLeft - diffX + 'px';
						LayerImages[l].style.top = LayerImages[l].offsetTop - diffY + 'px';
					}
					MySelf.zoomToScaledImage();
				}

			}
						
			var drawDiv = ReferenceIndicator;
			drawDiv.style.position = 'absolute';
			drawDiv.style.top = top + 'px';
			drawDiv.style.left = left + 'px';
			drawDiv.style.background = 'white';
			drawDiv.style.border = 'solid 1px black';
			drawDiv.style.width = newW+'px';
			drawDiv.style.height = newH+'px';
			drawDiv.style.zIndex = MAP_POPUP_ZINDEX;
			drawDiv.style.overflow = 'hidden';
			drawDiv.swapBG = '';
			drawDiv.swapBorder = 'solid 3px #A0A';
		/*	if(document.addEventListener) {
				drawDiv.addEventListener('keypress', function () { alert('hi'); }, true);
			}

			if(document.attachEvent) {
				document.attachEvent('onkeypress', ControlKeys);
			}*/
			setOpacity(drawDiv, 75);
			MapParent.appendChild(drawDiv);
			ReferenceIndicator.style.zIndex = MAP_CONTROL_INDEX+1;
		}
		var arr = new Array();
		for(var title in LayerImages) {
			arr[arr.length] = title;
			LayerImages[title].isLoaded = false;
		}
	/*	for(var i = 0; i < arr.length; i++) {
			Events.triggerEvent('refreshlayer', arr[i]);
		}*/
		MySelf.refreshLayer(arr);
	}

	function getStyleFunction(tagType, styleXML) {
		if(!styleXML) { return function(obj) { }; }
		var tag = styleXML.getElementsByTagName(tagType);
		var evalString = '';

		for(var t = 0; t < tag.length; t++) {
			var attrs = tag[t].getElementsByTagName('attr');
			for(var a = 0; a < attrs.length; a++) {
				evalString += ('obj.style.'+attrs[a].getAttribute('name')+'="'+attrs[a].getAttribute('value')+'";');
			}
		}	
		return function(obj) { eval(evalString); };
	}

	this.moveLayerUp = function(title) {
		MySelf.shiftLayer(title, 1);
	}

	this.moveLayerDown = function(title) {
		MySelf.shiftLayer(title, -1);

	}

	this.changeLayerOpacity = function(layerName, amount) {
		var img = LayerImages[layerName];
		var opac = getOpacity(img);
		opac+=amount;
		setOpacity(img, opac);
	}

	this.getOpacity = function(layerName) {
		return getOpacity(LayerImages[layerName]);
	}
	
	this.fadeLayer = function(title) {
		MySelf.changeLayerOpacity(title, -10);
	}

	this.unfadeLayer = function(title) {
		MySelf.changeLayerOpacity(title, 10);
	}

	this.reloadLayer = function(title) {
		var arr = new Array();
		arr[0] = title;
		MySelf.refreshLayer(arr);
	}
	
}
