function Draw(browser, divElement)
{
	var self = this;
	
	this.browser = browser;
	this.divElement = divElement;
	this.drawPlatform; // Vml.js or Canvas.js object type
	this.panning = false;
	this.points = new Array();
	this.currentX;
	this.currentY;
	this.startX;
	this.startY;
	this.doDraw = false;
	this.state;
	this.totalLength = 0;
	this.segLength = 0;
	this.area = 0;
	
	
	this.setDrawPlatform = setDrawPlatform;
	this.writeHtml = writeHtml;
	this.resizeElements = resizeElements;
	this.mapTool = mapTool;
	this.chkMouseUp = chkMouseUp;
	this.getMouse = getMouse;
	this.setState = setState;
	this.stopLine = stopLine;
	this.clearStatus = clearStatus;
	this.startPan = startPan;
	this.stopPan = stopPan;
	this.startBox = startBox;
	this.startPoly = startPoly;
	this.clearSelection = clearSelection;
	this.clear = clear;
	
	/* MUST CALL setDrawPlatform SO OBJECT REFERENCE IS CORRECT FOR BROWSER */
	this.setDrawPlatform();
	
	function setDrawPlatform()
	{
		if( browser.isInternetExplorer() )
			drawPlatform = new Vml();
		else
			drawPlatform = new Canvas();
	}
	
	function writeHtml()
	{
		if( browser.isInternetExplorer() )
		{
			// add shape element for VML
			document.getElementById(divElement).innerHTML = 
				"<v:shape id=\"theLine\" strokecolor=\"blue\" strokeweight=\"1pt\" coordsize=\"536,483\" style=\"LEFT:0px;WIDTH:551px;POSITION:absolute;TOP:0px;HEIGHT:485px\" filled=\"t\" fillcolor=\"blue\">" +
					"<v:fill id=\"fill\" opacity=\"9830f\" />" +
				"</v:shape>";
		}
		else
		{
			// add canvas element
			document.getElementById(divElement).innerHTML = "<canvas id=\"myCanvas\" width=\"1600px\" height=\"1200px\" style=\"left: 0px; top: 0px; border: 1px solid #000000;\" />";
		}
		
		// register events
		document.getElementById("divMap").onmousemove = self.getMouse;
		document.getElementById("divMap").onmousedown = self.mapTool;
		document.getElementById("divMap").onmouseup = self.chkMouseUp;
		document.getElementById("divMap").ondblclick = self.stopLine;
		document.getElementById("divMap").onmouseout = self.clearStatus;
	}
	
	function resizeElements()
	{
		document.getElementById(divElement).style.width = map.MapWidth;
		document.getElementById(divElement).style.height = map.MapHeight;
			
		if( browser.isInternetExplorer() )
		{
			document.getElementById("theLine").style.width = map.MapWidth;
			document.getElementById("theLine").style.height = map.MapHeight;
			document.getElementById("theLine").coordsize.value = map.MapWidth + " " + map.MapHeight;
		}
	}
	
	function mapTool(e)
	{
		if( browser.isInternetExplorer() )
		{
			self.currentX = event.clientX - map.MapLeft;
			self.currentY = event.clientY - map.MapTop;
		}
		else
		{
			self.currentX = e.clientX - map.MapLeft;
			self.currentY = e.clientY - map.MapTop;
		}
		
		switch( self.state )
		{
			case 'ZOOMIN':
			case 'ZOOMOUT':
			case 'SELECTRECT':
				self.startX = self.currentX;
				self.startY = self.currentY;
				startBox(self.startX, self.startY);
				break;	
			case 'SELECTPOLY':
				startPoly(e);
				break;
			case 'MEASURE':
				startPoly(e);
				break;
			case 'IDENTIFY':
				dist = ( map.getMaxX() - map.getMinX() ) / map.MapWidth * pixelTolerance;
				feature.getIdentify(self.currentX, self.currentY, dist);
				return false;
				break;
			case 'ADDTEXT':
				var text = document.getElementById("textToAdd").value; //prompt("Enter text to add","");
				document.getElementById("divAddText").style.display = "none";
				
				//document.getElementById("tdUpTop").innerHTML = "<img src=\"images4/header_tile.jpg\" width=\"80\" height=\"56\" alt=\"\">";
				if(text != null && text != ""){
				    var point = new Point();
				    x = (map.getMinX() * 1) + (self.currentX * (map.getMaxX() - map.getMinX())/map.MapWidth);
				    y = map.getMaxY() - (self.currentY * (map.getMaxY() - map.getMinY())/map.MapHeight);
				    point.setX(x);
				    point.setY(y);
				    point.setLabel(escape(text));
				    map.AcetatePoints.push(point);
				    map.updateMap();
				//dist = ( map.getMaxX() - map.getMinX() ) / map.MapWidth * pixelTolerance;
				//feature.getIdentify(self.currentX, self.currentY, dist);
				}
				else
				    document.getElementById("addtext").src = "images4/zc_btn_addtext.jpg";
				return false;
				break;
			case 'PAN':
				self.startX = self.currentX;
				self.startY = self.currentY;
				startPan(e);
				break;
			default:
				break;
		}
	}
	
	function chkMouseUp(e)
	{
		if( ((self.state == 'ZOOMIN') || (self.state == 'ZOOMOUT') || (self.state == 'SELECTRECT')) && (self.doDraw) )
			stopLine(e);
			
		if( (self.state == 'PAN') && (self.panning) )
			stopPan(e);
	}

	function getMouse(e)
	{
		if( browser.isInternetExplorer() )
		{
			self.currentX = event.clientX - map.MapLeft;
			self.currentY = event.clientY - map.MapTop;
		}
		else
		{
			self.currentX = e.clientX - map.MapLeft;
			self.currentY = e.clientY - map.MapTop;
		}
		
		if( toolTip.isFeatureToolTipDisplaying )
			toolTip.hideToolTip();
		
		toolTip.x = self.currentX;
		toolTip.y = self.currentY;
		
		if( toolTip.featureToolTipInterval == null )
			toolTip.featureToolTipInterval = setInterval('toolTip.showFeatureToolTip()', 500);
		
		toolTip.lastMoveDateTime = new Date();
		
		if( self.currentX < 0 )
			self.currentX = 0;
		else if( self.currentX > map.MapWidth )
			self.currentX = map.MapWidth;
		
		if( self.currentY < 0 )
			self.currentY = 0;
		else if( self.currentY > map.MapHeight )
			self.currentY = map.MapHeight;
		
		if( mapLoaded )
		{
			mouseX = (map.getMaxX() - map.getMinX())/map.MapWidth * self.currentX + parseFloat(map.getMinX());
			mouseY = (map.getMaxY() - map.getMinY())/map.MapHeight * (map.MapHeight - self.currentY) + parseFloat(map.getMinY());
			
			//show lat/long
			//calcLccLamr1 accepts METERS, so we must test our map units and convert to meters
			if( map.Units == "METERS" )
			{
				lat = calcLccLamr1( map.Projection, mouseY, mouseX )["lat"];
				lng = calcLccLamr1( map.Projection, mouseY, mouseX )["lng"];
			}
			else
			{
				lat = calcLccLamr1( map.Projection, convertDistanceUnits(mouseY,map.Units,"METERS"), convertDistanceUnits(mouseX,map.Units,"METERS") )["lat"];
				lng = calcLccLamr1( map.Projection, convertDistanceUnits(mouseY,map.Units,"METERS"), convertDistanceUnits(mouseX,map.Units,"METERS") )["lng"];
			}
			
			var utm = new Array();
			utm = calcLCCSP83("UTM17",lat,lng);
			
			window.status = "X: " + mouseX.toFixed(2) + ", Y: " + mouseY.toFixed(2) + " (Lat: " + lat.toFixed(2) + ", Long: -" + lng.toFixed(2) + ")" + " (UTM North: " + utm["north"].toFixed(2) + " UTM East: " + utm["east"].toFixed(2) + ")";
		}
		
		if( self.doDraw )
		{
			//alert(self.state);
			switch( self.state )
			{
				case 'ZOOMIN':
				case 'ZOOMOUT':
				case 'SELECTRECT':
					drawPlatform.drawRectangle(self.startX, self.startY, self.currentX, self.currentY);
					break;
					
				case 'SELECTPOLY':
					drawPlatform.drawPolyline(self.points, self.currentX, self.currentY);
					break;
					
				case 'MEASURE':
					drawPlatform.drawPolyline(self.points, self.currentX, self.currentY);
					self.segLength = calcDistance(self.points[self.points.length - 1].split(',')[0], self.points[self.points.length - 1].split(',')[1], self.currentX, self.currentY);
					self.area = calcArea(self.points, self.currentX, self.currentY);
					
					switch(map.Units)
					{
						case 'METERS':
							var strStatus = "Total Length: " + convertDistanceUnits(self.totalLength, "METERS", "FEET").toFixed(2) + " ft ";
							strStatus += "(" + convertDistanceUnits(self.totalLength, "METERS", "MILES").toFixed(2) + " miles), ";
							strStatus += "Segment Length: " + convertDistanceUnits(self.segLength, "METERS", "FEET").toFixed(2) + " ft";
							strStatus += " -- Area: " + convertAreaUnits(self.area, "METERS", "FEET").toFixed(2) + " sq ft, " + convertAreaUnits(self.area, "METERS", "ACRES").toFixed(2) + " acres";
							window.status = strStatus;
							break;
							
						case 'FEET':
							var strStatus = "Total Length: " + self.totalLength.toFixed(2) + " ft ";
							strStatus += "(" + convertDistanceUnits(self.totalLength, "FEET", "MILES").toFixed(2) + " miles), ";
							strStatus += "Segment Length: " + self.segLength.toFixed(2) + " ft";
							strStatus += " -- Area: " + self.area.toFixed(2) + " sq ft, " + convertAreaUnits(self.area, "FEET", "ACRES").toFixed(2) + " acres";
							window.status = strStatus;
							break;
					}
					
					break;
			}
		}	
		else
		{
			if( self.panning )
			{
				document.getElementById("mapImage").style.top = self.currentY - self.startY;
				document.getElementById("mapImage").style.left = self.currentX - self.startX;
			}
		}
	}

	function setState(newstate)
	{
		var prevState = newstate;
		self.state = newstate;
		
		var arr = divTools.getElementsByTagName("img");
		
		for( var j = 0; j < arr.length; j++ )
		{
			if( arr[j].src.indexOf("-over") > 0 )
				arr[j].src = arr[j].src.replace("-over","");
		}
			
		
		switch(newstate)
		{
			case 'ZOOMIN':
				drawPlatform.setFillColor("#00FF00");
				drawPlatform.setStrokeColor("#00FF00");
				drawPlatform.isFill = true;
				zoomin.src = "images4/zc_btn_zoomin-over.jpg";
				document.getElementById("divAddText").style.display = "none";
				    
				break;
			case 'ZOOMOUT':
				drawPlatform.setFillColor("#FF0000");
				drawPlatform.setStrokeColor("#FF0000");
				drawPlatform.isFill = true;
				zoomout.src ="images4/zc_btn_zoomout-over.jpg";
				document.getElementById("divAddText").style.display = "none";
				    
				break;
			case 'SELECTPOLY':
				drawPlatform.setFillColor("#FF0000");
				drawPlatform.setStrokeColor("#FF0000");
				drawPlatform.isFill = true;
				selectpoly.src = "images4/zc_btn_selpoly-over.jpg";
				document.getElementById("divAddText").style.display = "none";
				    
				break;
			case 'SELECTRECT':
				drawPlatform.setFillColor("#FF0000");
				drawPlatform.setStrokeColor("#FF0000");
				drawPlatform.isFill = true;
				selectrect.src = "images4/zc_btn_selbox-over.jpg";
				document.getElementById("divAddText").style.display = "none";
				    
				break;
			case 'MEASURE':
				drawPlatform.setFillColor("#0000FF");
				drawPlatform.setStrokeColor('#0000FF');
				
				
				drawPlatform.isFill = true;
				measure.src = "images4/zc_btn_measure-over.jpg";
				document.getElementById("divAddText").style.display = "none";
				    
				break;
			case 'PAN':
				pan.src = "images4/zc_btn_pan-over.jpg"
				document.getElementById("divAddText").style.display = "none";
				    
				break;
			case 'IDENTIFY':
				identify.src = "images4/zc_btn_ident-over.jpg";
				document.getElementById("divAddText").style.display = "none";
				    
				break;
			case 'ADDTEXT':
			    if(document.getElementById("divAddText").style.display == "none")
			    {
			        if(document.getElementById("textToAdd") && document.getElementById("textToAdd").value != "" && document.getElementById("textToAdd").value != null)
			        {
			            document.getElementById("textToAdd").value = "";
			            document.getElementById("addtext").src = "images4/zc_btn_addtext.jpg";
			            break;
			        }
				    addtext.src = "images4/zc_btn_addtext-over.jpg";
				    document.getElementById("divAddText").innerHTML = " Enter Text to Add and Click Map: <br/> <input id=\"textToAdd\" type=\"text\"> ";
				    document.getElementById("divAddText").style.width = 180;
				    document.getElementById("divAddText").style.display = "block";
				    document.getElementById("divAddText").style.right = 50;
				    document.getElementById("divAddText").style.bottom = 100;
				    document.getElementById("divAddText").style.height = 15;
				    document.getElementById("divAddText").style.zIndex = 99;
				    document.getElementById("divAddText").style.backgroundColor = "#FFFFFF";
				    
				    
				}
				else
				{
				    document.getElementById("divAddText").style.display = "none";
				    document.getElementById("textToAdd").value = "";
				    addtext.src = "images4/zc_btn_addtext.jpg";
				
				}
				//document.getElementById("div").style.background = "url(images4/header_tile.jpg)";
				
				
				break;
		}
	}

	function stopLine(e)
	{
		switch(self.state)
		{
			case 'ZOOMIN':
			
				if( (Math.abs(self.currentX - self.startX) < 2) || (Math.abs(self.currentY - self.startY) < 2) )
				{
					dx = (map.getMaxX() - map.getMinX()) / 4;
					dy = (map.getMaxY() - map.getMinY()) / 4;
					
					arrPt = map.toMapPoint(self.startX,self.startY);
					var x1 = arrPt[0] - dx;
					var y1 = arrPt[1] - dy;
					var x2 = arrPt[0] + parseFloat(dx);
					var y2 = arrPt[1] + parseFloat(dy); 
					
					map.getMap(self.state, x1, y1, x2, y2, true);
				}	
				else
				{
					arrPt1 = map.toMapPoint(self.startX,self.startY);
					arrPt2 = map.toMapPoint(self.currentX,self.currentY);
							
					var x1 = arrPt1[0];
					var y1 = arrPt1[1];
					var x2 = arrPt2[0];
					var y2 = arrPt2[1];
					
					if (x2 < x1)
					{
						tempX = x1;
						x1 = x2;
						x2 = tempX;
					}
					
					if (y2 < y1)
					{
						tempY = y1;
						y1 = y2;
						y2 = tempY;
					}
					
					map.getMap("ZOOMIN", x1, y1, x2, y2, true);
				}
				break;
				
			case 'ZOOMOUT':
			
				if( (Math.abs(self.currentX - self.startX) < 2) || (Math.abs(self.currentY - self.startY) < 2) )
				{
					var dx = (map.getMaxX() - map.getMinX());
					var dy = (map.getMaxY() - map.getMinY());
					
					var arrPt = map.toMapPoint(self.startX, self.startY);
					var x1 = arrPt[0] - dx;
					var y1 = arrPt[1] - dy;
					var x2 = arrPt[0] + parseFloat(dx);
					var y2 = arrPt[1] + parseFloat(dy); 
					
					map.getMap(self.state, x1, y1, x2, y2, true);
				}	
				else
				{
					var arrPt1 = map.toMapPoint(self.startX, self.startY);
					var arrPt2 = map.toMapPoint(self.currentX, self.currentY);
					
					var x1 = arrPt1[0];
					var y1 = arrPt1[1];
					var x2 = arrPt2[0];
					var y2 = arrPt2[1];
					
					if (x2 < x1)
					{
						tempX = x1;
						x1 = x2;
						x2 = tempX;
					}
					
					if (y2 < y1)
					{
						tempY = y1;
						y1 = y2;
						y2 = tempY;
					}
					
					dx = (map.getMaxX() - map.getMinX());
					dy = (map.getMaxY() - map.getMinY());
					
					cx = (x2 - x1) / 2 + parseFloat(x1);
					cy = (y2 - y1) / 2 + parseFloat(y1);
					
					dx = dx * dx / Math.abs(x2 - x1) / 2;
					dy = dy * dy / Math.abs(y2 - y1) / 2;
					
					x1 = cx - dx;
					y1 = cy - dy;
					x2 = parseFloat(cx) + parseFloat(dx);
					y2 = parseFloat(cy) + parseFloat(dy);
					
					map.getMap(self.state, x1, y1, x2, y2, true);
				}
				break;
				
			case 'SELECTRECT':
			
				self.points.push(self.startX + "," + self.startY);
				if ((Math.abs(self.currentX - self.startX) > pixelTolerance) || (Math.abs(self.currentY - self.startY) > pixelTolerance))
				{
					self.points.push(self.currentX + "," + self.startY);
					self.points.push(self.currentX + "," + self.currentY);
					self.points.push(self.startX + "," + self.currentY);
				}
				else
				{
					self.points.push( (self.startX + parseFloat(pixelTolerance)) + "," + self.startY );
					self.points.push( (self.startX + parseFloat(pixelTolerance)) + "," + (self.startY + parseFloat(pixelTolerance)) );
					self.points.push( self.startX + "," + (self.startY + parseFloat(pixelTolerance)) );
				}
				
			case 'SELECTPOLY':
				spatialSelect(self.state, self.points, false);
				break;
				
			case 'MEASURE':
				dstr = "TOTAL DISTANCE:"
				dstr += "\n\tFeet: " + convertDistanceUnits(self.totalLength, map.Units, "FEET").toFixed(2);
				dstr += "\n	Meters: " + convertDistanceUnits(self.totalLength, map.Units, "METERS").toFixed(2);
				dstr += "\n	Miles: " + convertDistanceUnits(self.totalLength, map.Units, "MILES").toFixed(2);
				dstr += "\n\nTOTAL AREA:";
				dstr += "\n	Sq Feet: " + convertAreaUnits(self.area, map.Units, "FEET").toFixed(2);
				dstr += "\n	Sq Meters: " + convertAreaUnits(self.area, map.Units, "METERS").toFixed(2);
				dstr += "\n	Sq Miles: " + convertAreaUnits(self.area, map.Units, "MILES").toFixed(2);
				dstr += "\n	Acres: " + convertAreaUnits(self.area, map.Units, "ACRES").toFixed(2);
				
				self.totalLength = 0;
				
				
				alert(dstr);
				break;
		}
		
		self.doDraw = false;
		self.points = new Array();
		drawPlatform.clear();
	}

	function stopPan(e)
	{
		
		self.panning = false;
		
		var arrPt1 = map.toMapPoint(self.startX, self.startY);
		var arrPt2 = map.toMapPoint(self.currentX, self.currentY);
		
		if( (Math.abs(self.currentX - self.startX) < 2) || (Math.abs(self.currentY - self.startY) < 2) )
		{
			dX = (map.getMaxX() - map.getMinX()) / 2;
			dY = (map.getMaxY() - map.getMinY()) / 2;
					
			map.getMap(self.state, (arrPt1[0] - dX), (arrPt1[1] - dY), (arrPt1[0] + parseFloat(dX)), (arrPt1[1] + parseFloat(dY)), true);
		}	
		else
		{
			dX = arrPt2[0] - arrPt1[0];
			dY = arrPt2[1] - arrPt1[1];
			
			map.getMap(self.state, (map.getMinX() - dX), (map.getMinY() - dY), (map.getMaxX() - dX), (map.getMaxY() - dY), true);
		}
	}

	function startBox(x,y)
	{
		self.doDraw = true;
		drawPlatform.drawRectangle(x, y, x, y);
		return false;
	}

	function startPoly(e)
	{
		if( browser.isInternetExplorer() )
			event.cancelBubble = true;
		else
			e.cancelBubble = true;
		
		self.doDraw = true;
		self.points.push(self.currentX + "," + self.currentY);
		
		drawPlatform.drawPolyline(self.points, null, null);
		
		if( self.state == "MEASURE" )
		{
			if( self.points.length == 0 )
				self.totalLength = 0;
			else
			{
				self.totalLength = self.totalLength + self.segLength;
					
			}
				
			self.segLength = 0;
		}
		
		return false;
	}

	function startPan(e)
	{
		self.panning = true;
	}
	
	function clearStatus()
	{
		window.status = "";
		
		toolTip.hideToolTip();
		clearInterval(toolTip.featureToolTipInterval);
		toolTip.featureToolTipInterval = null;
	}
	
	function clearSelection(clearMap)
	{
		if( clearMap )
			showLoading();
		
		// reset active tool
		//draw.setState("ZOOMIN");
		
		var layer;
		
		for( var i = 0; i < layerArray.length; i++ )
		{
			layer = layerArray[i];
			layer.SpatialFilter = new SpatialFilter();
		}
		
		// remove acetate layer from map object
		map.AcetatePoints = new Array();
		
		//empty the info table...# of results, etc.
		spnResultsInfo.innerHTML = ""
		spnDetailsInfo.innerHTML = "There are no details to display."
		
		//delete current results
		document.getElementById("divResultsList").innerHTML = "";	
		//delete details
		document.getElementById("divDetailsList").innerHTML = "";
				
		// send request to web service to get new map
		if( clearMap )
		{
			map.getMap(draw.state, map.getMinX(), map.getMinY(), map.getMaxX(), map.getMaxY(), false);
			activateTab("tabLayers");
		}
	}
	
	function clear()
	{
		self.doDraw = false;
		self.points = new Array();
		drawPlatform.clear();
		
	}
}