// Development (local)
/*var rootUrl = 'http://localhost/ShenandoahIMS/';
var server = 'http://localhost/ShenandoahIMS/webservices/';
var browserUrl = 'http://localhost/ShenandoahIMS/browser.aspx';*/

// Staging (dev-web01)
/*var rootUrl = 'http://demo.timmons.com/ShenandoahIMS/';
var server = 'http://demo.timmons.com/ShenandoahIMS/webservices/';
var browserUrl = 'http://demo.timmons.com/ShenandoahIMS/browser.aspx';*/

var browserUrl = 'http://www.shenandoahgis.org/browser.aspx';

// relative

var rootUrl = './';
var server = './webservices/';

var mapUnits = "FEET"; //Needed for calculating distance, scale, etc.
var mapProj = "VAN"; //projection of the map.  VALAM - VDOT Lambert, VAS - Virginia South...
var layerArray = new Array(); // Array of Layer objects
var mapArray = new Array(); // Array of Map objects
var mapArrayIndex;
var map = new Map();
var activeLayer = 12; //maintain active layer position number
var mapLoaded = false; //determines whether the map info has been returned

var sizing = false;
var arrPoints = new Array();
var moving;
var panning = false;
var doDraw = false;
var firstTime = true;
var selectMode = 0; //0 - make new selection, 1 - add to/remove from selection (not yet implemented)
var pixelTolerance = 20; //pixel tolerance used for selecting by point
var zoomTolerance = 1000;//envelope size when zooming to a point
var prevState = 'ZOOMIN';//store the previous state so we can switch back if needed

var x1;
var y1;
var x2;
var y2;

//******************Zoom Slider******************************
var zs = new ZoomSlider();
zs.Mode = 0;//0 - Fixed Scale, 1 - Fixed Width. sets how the zoom slider bar works
zs.Orientation = 0;//0 - horizontal, 1 - vertical.
zs.WidthUnits = "FEET";

zs.ScaleArray[0] = 1200;
zs.ScaleArray[1] = 2400;
zs.ScaleArray[2] = 4800;
zs.ScaleArray[3] = 6000;
zs.ScaleArray[4] = 7200;
zs.ScaleArray[5] = 10000;
zs.ScaleArray[6] = 24000;
zs.ScaleArray[7] = 50000;
zs.ScaleArray[8] = 100000;
zs.ScaleArray[9] = 250000;

zs.ScaleLabelArray = zs.ScaleArray;

zs.WidthArray[0] = 0.1;
zs.WidthArray[1] = 0.2;
zs.WidthArray[2] = 0.3;
zs.WidthArray[3] = 0.5;
zs.WidthArray[4] = 1;
zs.WidthArray[5] = 2;
zs.WidthArray[6] = 5;
zs.WidthArray[7] = 10;
zs.WidthArray[8] = 15;
zs.WidthArray[9] = 20;
zs.WidthArray[10] = 30;
zs.WidthArray[11] = 50;
zs.WidthArray[12] = 100;
zs.WidthArray[13] = 200;
zs.WidthArray[14] = 500;

zs.WidthLabelArray = zs.WidthArray;

//****************************************************

function chkMouseUp(e)
{
	if( ((state == 'ZOOMIN') || (state == 'ZOOMOUT') || (state == 'SELECTRECT')) && (doDraw) )
		stopLine(e);
		
	if( (state == 'PAN') && (panning) )
		stopPan(e);
}

function getMouse(e)
{
	x2 = event.clientX - map.MapLeft;
	y2 = event.clientY - map.MapTop;
	
	if(x2 < 0)
		x2 = 0;
	else if(x2 > map.MapWidth)
		x2 = map.MapWidth;
	
	if(y2 < 0)
		y2 = 0;
	else if(y2 > map.MapHeight)
		y2 = map.MapHeight;
	
	if (mapLoaded)
	{
		mouseX = (map.getMaxX() - map.getMinX())/map.MapWidth * x2 + parseFloat(map.getMinX());
		mouseY = (map.getMaxY() - map.getMinY())/map.MapHeight * (map.MapHeight - y2) + 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(mapProj,mouseY,mouseX)["lat"];
			lng = calcLccLamr1(mapProj,mouseY,mouseX)["lng"];
		}
		else
		{
			lat = calcLccLamr1(mapProj,convertDistanceUnits(mouseY,map.Units,"METERS"),convertDistanceUnits(mouseX,map.Units,"METERS"))["lat"];
			lng = calcLccLamr1(mapProj,convertDistanceUnits(mouseY,map.Units,"METERS"),convertDistanceUnits(mouseX,map.Units,"METERS"))["lng"];
		}
		
		window.status = "X: " + mouseX.toFixed(2) + ", Y: " + mouseY.toFixed(2) + " (Lat: " + lat.toFixed(2) + ", Long: -" + lng.toFixed(2) + ")";
	}
	
	if(doDraw)
	{
		switch(state)
		{
			case 'ZOOMIN':
			case 'ZOOMOUT':
			case 'SELECTRECT':
			
				theLine.path.value = "m " + x1 + "," + y1 + " l " + x1 + "," + y2 + " l " + x2 + "," + y2 + " l " + x2 + "," + y1 + "x e";
				break;
				
			case 'SELECTPOLY':
			
				if (tempPoints.indexOf("x") > 0)
					tempPoints = tempPoints.substr(0,tempPoints.indexOf("x"));
				
				theLine.path.value = tempPoints + " l " + x2 + "," + y2 + "x e";
				break;
				
			case 'SELECTLINE':
			
				if (tempPoints.indexOf("e") > 0)
					tempPoints = tempPoints.substr(0,tempPoints.indexOf("e"));
				
				theLine.path.value = tempPoints + " l " + x2 + "," + y2;
				break;
				
			case 'MEASURE':
			
				if (tempPoints.indexOf("e") > 0)
					tempPoints = tempPoints.substr(0,tempPoints.indexOf("e"));
				
				theLine.path.value = tempPoints + " l " + x2 + "," + y2;
				segLength = calcDistance(x1,y1,x2,y2);
				
				area = calcArea(arrPoints,x2,y2);
				
				switch(map.Units)
				{
					case 'METERS':
						strStatus = "Total Length: " + convertDistanceUnits(totalLength,"METERS","FEET").toFixed(2) + " ft ";
						strStatus += "(" + convertDistanceUnits(totalLength,"METERS","MILES").toFixed(2) + " miles), ";
						strStatus += "Segment Length: " + convertDistanceUnits(segLength,"METERS","FEET").toFixed(2) + " ft";
						strStatus += " -- Area: " + convertAreaUnits(area,"METERS","FEET").toFixed(2) + " sq ft, " + convertAreaUnits(area,"METERS","ACRES").toFixed(2) + " acres";
						window.status = strStatus;//"Total Length: " + totalLength.toFixed(2) + " meters (" + (totalLength/0.3048/5280).toFixed(2) + " miles), Segment Length: " + segLength.toFixed(2) + " meters"; 
						break;
						
					case 'FEET':
						strStatus = "Total Length: " + totalLength.toFixed(2) + " ft ";
						strStatus += "(" + convertDistanceUnits(totalLength,"FEET","MILES").toFixed(2) + " miles), ";
						strStatus += "Segment Length: " + segLength.toFixed(2) + " ft";
						strStatus += " -- Area: " + area.toFixed(2) + " sq ft, " + convertAreaUnits(area,"FEET","ACRES").toFixed(2) + " acres";
						window.status = strStatus;//"Total Length: " + totalLength.toFixed(2) + " ft (" + (totalLength/5280).toFixed(2) + " miles), Segment Length: " + segLength.toFixed(2) + " ft"; 
						break;
				}
				
				break;
		}
	}	
	else
	{
		if(panning)
		{
			document.getElementById("mapImage").style.top = y2 - y1 + "px";
			document.getElementById("mapImage").style.left = x2 - x1 + "px";
		}
	}
}

function mapTool(e)
{
	x1 = event.clientX - map.MapLeft;
	y1 = event.clientY - map.MapTop;
		
	switch(state)
	{
		case 'ZOOMIN':
			startBox(e);
			break;
		case 'ZOOMOUT':
			startBox(e);
			break;
		case 'SELECTRECT':
			startBox(e);
			break;	
		case 'SELECTPOLY':
			startPoly(e);
			break;
		case 'SELECTLINE':
		case 'MEASURE':
			startLine(e);
			break;
		case 'IDENTIFY':
			dist = ( map.getMaxX() - map.getMinX() ) / map.MapWidth * pixelTolerance;
			var feat = new Feature();
			feat.processIdentify(x1, y1, dist);
			return false;
			break;
		case 'PAN':
			startPan(e);
			break;
		default:
			break;	
	}
}

function setState(newstate)
{
	prevState = newstate;
	state = newstate;
	
	var arr = divTools.getElementsByTagName("img");
		
	for(var j=0; j < arr.length; j++)
	{
		if( arr[j].src.indexOf("_act") > 0 )
			arr[j].src = arr[j].src.replace("_act","_inact");
	}
	
	arr = divTools.getElementsByTagName("td");
		
	for(var j=0; j < arr.length; j++)
	{
		if (arr[j].className == "toolActive")
			arr[j].className = "toolNormal";
	}
	
	if (event.srcElement)
		event.cancelBubble = true;
	
	switch(newstate)
	{
		case 'ZOOMIN':
			fill.color = "#00ff00";
			theLine.strokecolor = "#00ff00";
			fill.on = "true";
			zoomin.src = zoomin.src.replace("_inact","_act");
			zoomin.className = "toolActive";
			break;
		case 'ZOOMOUT':
			fill.color = "red";
			theLine.strokecolor = "red";
			fill.on = "true";
			zoomout.src = zoomout.src.replace("_inact","_act");
			zoomout.className = "toolActive";
			break;
		case 'SELECTPOLY':
			fill.color = "red";
			theLine.strokecolor = "red";
			fill.on = "true";
			selectpoly.src = selectpoly.src.replace("_inact","_act");
			selectpoly.className = "toolActive";
			break;
		case 'SELECTRECT':
			fill.color = "red";
			theLine.strokecolor = "red";
			fill.on = "true";
			selectrect.src = selectrect.src.replace("_inact","_act");
			selectrect.className = "toolActive";
			break;	
		case 'SELECTLINE':
			fill.color = "red";
			theLine.strokecolor = "red";
			fill.on = "false";
			selectline.src = selectline.src.replace("_inact","_act");
			selectline.className = "toolActive";
			break;
		case 'MEASURE':
			fill.color = "blue";
			theLine.strokecolor = "blue";
			fill.on = "true";
			measure.src = measure.src.replace("_inact","_act");
			measure.className = "toolActive";
			break;
		case 'PAN':
			pan.src = pan.src.replace("_inact","_act");
			pan.className = "toolActive";
			break;
		case 'IDENTIFY':
			identify.src = identify.src.replace("_inact","_act");
			identify.className = "toolActive";
			break;
	}
}

function startLine(e)
{
	event.cancelBubble = true;
	draw.style.visibility = 'visible';
	
	if(firstTime)
	{
		firstTime = false;
		doDraw = true;
		theLine.path.value = "m " + x1 + "," + y1;
		
		if (state == "MEASURE")
		{
			totalLength = 0;
			segLength = 0;
		}
		
		arrPoints[arrPoints.length] = x1;
		arrPoints[arrPoints.length] = y1;
	}
	else
	{
		if(tempPoints.indexOf("e") > 0)
			tempPoints = tempPoints.substr(0,tempPoints.indexOf("e"));
			
		theLine.path.value = tempPoints + " l " + x1 + "," + y1;
		
		if (state == "MEASURE")
		{
			totalLength = totalLength + segLength;
			segLength = 0;
		}
		
		arrPoints[arrPoints.length] = x2;
		arrPoints[arrPoints.length] = y2;
	}
	
	tempPoints = theLine.path.value;
	return false;
}

function startPan(e)
{
	panning = true;
}

function stopLine(e)
{
	firstTime = true;
	doDraw = false;
	tool = false;
	
	switch(state)
	{
		case 'ZOOMIN':
		
			if( (Math.abs(x2-x1) < 2) || (Math.abs(y2-y1) < 2) )
			{
				dx = (map.getMaxX() - map.getMinX()) / 4;
				dy = (map.getMaxY() - map.getMinY()) / 4;
				
				arrPt = map.toMapPoint(x1,y1);
				x1 = arrPt[0] - dx;
				y1 = arrPt[1] - dy;
				x2 = arrPt[0] + parseFloat(dx);
				y2 = arrPt[1] + parseFloat(dy); 
				
				map.getMap(state, x1, y1, x2, y2, true);
			}	
			else
			{
				arrPt1 = map.toMapPoint(x1,y1);
				arrPt2 = map.toMapPoint(x2,y2);
						
				x1 = arrPt1[0];
				y1 = arrPt1[1];
				x2 = arrPt2[0];
				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(x2-x1) < 2) || (Math.abs(y2-y1) < 2) )
			{
				dx = (map.getMaxX() - map.getMinX());
				dy = (map.getMaxY() - map.getMinY());
				
				arrPt = map.toMapPoint(x1,y1);
				x1 = arrPt[0] - dx;
				y1 = arrPt[1] - dy;
				x2 = arrPt[0] + parseFloat(dx);
				y2 = arrPt[1] + parseFloat(dy); 
				
				map.getMap(state, x1, y1, x2, y2, true);
			}	
			else
			{
				arrPt1 = map.toMapPoint(x1,y1);
				arrPt2 = map.toMapPoint(x2,y2);
				
				x1 = arrPt1[0];
				y1 = arrPt1[1];
				x2 = arrPt2[0];
				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(state, x1, y1, x2, y2, true);
			}
			break;
			
		case 'SELECTRECT':
		
			arrPoints[arrPoints.length] = x1;
			arrPoints[arrPoints.length] = y1;
			if ((Math.abs(x2-x1) > pixelTolerance) || (Math.abs(y2-y1) > pixelTolerance))
			{
				arrPoints[arrPoints.length] = x2;
				arrPoints[arrPoints.length] = y1;
				arrPoints[arrPoints.length] = x2;
				arrPoints[arrPoints.length] = y2;
				arrPoints[arrPoints.length] = x1;
				arrPoints[arrPoints.length] = y2;
			}
			else
			{
				arrPoints[arrPoints.length] = x1 + parseFloat(pixelTolerance);
				arrPoints[arrPoints.length] = y1;
				arrPoints[arrPoints.length] = x1 + parseFloat(pixelTolerance);
				arrPoints[arrPoints.length] = y1 + parseFloat(pixelTolerance);
				arrPoints[arrPoints.length] = x1;
				arrPoints[arrPoints.length] = y1 + parseFloat(pixelTolerance);
			}
			
		case 'SELECTLINE':
		case 'SELECTPOLY':
			spatialSelect(state, arrPoints, false);
			break;
		case 'MEASURE':
			dstr = "TOTAL DISTANCE:";
			dstr += "\n	Feet: " + convertDistanceUnits(totalLength,map.Units,"FEET").toFixed(2);
			dstr += "\n	Meters: " + convertDistanceUnits(totalLength,map.Units,"METERS").toFixed(2);
			dstr += "\n	Miles: " + convertDistanceUnits(totalLength,map.Units,"MILES").toFixed(2);
			dstr += "\n\nTOTAL AREA:";
			dstr += "\n	Sq Feet: " + convertAreaUnits(area,map.Units,"FEET").toFixed(2);
			dstr += "\n	Sq Meters: " + convertAreaUnits(area,map.Units,"METERS").toFixed(2);
			dstr += "\n	Sq Miles: " + convertAreaUnits(area,map.Units,"MILES").toFixed(2);
			dstr += "\n	Acres: " + convertAreaUnits(area,map.Units,"ACRES").toFixed(2);
			alert(dstr);
			break;
	}
	
	if( state != "ADDCUSTOMIMPACT" )
	{
		theLine.path.value = '';
		draw.style.visibility = 'hidden';
		arrPoints.length = 0;
		window.status = "";
	}
}

function stopPan(e)
{
	panning = false;
	tool = false;
	
	if( (Math.abs(x2-x1) < 2) || (Math.abs(y2-y1) < 2) )
	{
		arrPt1 = map.toMapPoint(x1,y1);
		arrPt2 = map.toMapPoint(x2,y2);
		dX = (map.getMaxX() - map.getMinX()) / 2;
		dY = (map.getMaxY() - map.getMinY()) / 2;
				
		map.getMap(state, (arrPt1[0] - dX), (arrPt1[1] - dY), (arrPt1[0] + parseFloat(dX)), (arrPt1[1] + parseFloat(dY)), true);
	}	
	else
	{
		arrPt1 = map.toMapPoint(x1,y1);
		arrPt2 = map.toMapPoint(x2,y2);
		dX = arrPt2[0] - arrPt1[0];
		dY = arrPt2[1] - arrPt1[1];
		
		map.getMap(state, (map.getMinX() - dX), (map.getMinY() - dY), (map.getMaxX() - dX), (map.getMaxY() - dY), true);
	}
}

function startBox(e)
{
	doDraw = true;
	draw.style.visibility = 'visible';
	theLine.path.value = "m " + x1 + "," + y1 + "x e";
	return false;
}

function startPoly(e)
{
	event.cancelBubble = true;
	
	if(firstTime)
	{
		arrPoints.length = 0;
		firstTime = false;
		doDraw = true;
		theLine.path.value = "m " + x1 + "," + y1 + "x e";
		draw.style.visibility = 'visible';
		arrPoints[arrPoints.length] = x1;
		arrPoints[arrPoints.length] = y1;
	}
	else
	{
		if( tempPoints.indexOf("x") > 0 )
			tempPoints = tempPoints.substr(0,tempPoints.indexOf("x"));
		
		theLine.path.value = tempPoints + " l " + x2 + "," + y2 + "x e";
		arrPoints[arrPoints.length] = x2;
		arrPoints[arrPoints.length] = y2;
	}
	
	tempPoints = theLine.path.value;
	return false;
}

function calcDistance(x1,y1,x2,y2)
{
 	var dist;
	var thescale = (map.getMaxX() - map.getMinX()) / map.MapWidth;
	dist = Math.sqrt(Math.pow((thescale * (x2 - x1)),2) + Math.pow((thescale * (y2 - y1)),2));
 	return dist;
 }
 
 function calcArea(arr,x,y){

	var arrX = new Array();
	var arrY = new Array();
	
	//Split the array into two arrays
	for(var j=0; j < arr.length; j++)
	{
		if(j%2 == 0){
			arrX[arrX.length] = arr[j];// * mapScale / 0.3048;
		}else{
			arrY[arrY.length] = arr[j];// * mapScale / 0.3048;
		}
	}
	
	if (x && y)
	{
		arrX[arrX.length] = x;// * mapScale / 0.3048;
		arrY[arrY.length] = y;// * mapScale / 0.3048;
	}
	
	area = 0;
	
	for(var i=0; i < arrX.length; i++){
		if (i == arrX.length - 1){
			area += (arrX[i] * arrY[0] - arrX[0] * arrY[i]);
		}else{
			area += (arrX[i] * arrY[i + 1] - arrX[i + 1] * arrY[i]);
		}
	}
	area = 0.5 * area; // in pixels
	
	//Convert Square Pixels to Square Map Units
	var unitsPerPixel = (map.getMaxX() - map.getMinX()) / map.MapWidth;
	area = area * Math.pow(unitsPerPixel,2);
	
	return Math.abs(area);//in map units
}

function resizeElements()
{
	divTabsTop = 75;
	divMapTop = 75;
	divMapLeft = 5;
	divTabsWidth = 330;
	
	divTabs.style.height = document.body.clientHeight - divTabsTop - 10;
	divTabs.style.left = document.body.clientWidth - divTabsWidth - 15;
	
	divLayers.style.height = parseInt(divTabs.style.height) - 35;
	divLayersList.style.height = parseInt(divTabs.style.height) - 35 - 55;
	
	divInformation.style.height = parseInt(divTabs.style.height) - 35;
	divInformationList.style.height = parseInt(divTabs.style.height) - 35 - 40;
	divInformationMessage.style.height = parseInt(divTabs.style.height) - 35 - 40;
	
	divResults.style.height = parseInt(divTabs.style.height) - 35;
	divResultsList.style.height = parseInt(divTabs.style.height) - 35 - 40;
	divDetailsList.style.height = parseInt(divTabs.style.height) - 35 - 40;
	
	divSearch.style.height = parseInt(divTabs.style.height) - 35;
	divParcelSearchList.style.height = parseInt(divTabs.style.height) - 35 - 40;
	
	divLegend.style.height = parseInt(divTabs.style.height) - 35;
	
	divFindFeatureList.style.height = parseInt(divTabs.style.height) - 110;
	
	divLayerLabels.style.height = parseInt(divTabs.style.height) - 110;
	
	divMap.style.height = document.body.clientHeight - divMapTop - 68;
	divMap.style.width = document.body.clientWidth - 330 - 30;
	map.MapWidth = parseInt(divMap.style.width);
	map.MapHeight = parseInt(divMap.style.height);
	map.MapLeft = parseInt(divMapLeft);
	map.MapTop = parseInt(divMapTop);
	divMapImage.style.width = map.MapWidth;
	divMapImage.style.height = map.MapHeight;
	mapImage.style.width = map.MapWidth;
	mapImage.style.height = map.MapHeight;
	
	divZoomSlider.style.width = map.MapWidth;
	divZoomSlider.style.top = map.MapTop + map.MapHeight + 5;
	
	draw.style.width =  map.MapWidth;
	draw.style.height = map.MapHeight;
	theLine.style.width =  map.MapWidth;
	theLine.style.height = map.MapHeight;
	theLine.coordsize.value = map.MapWidth + " " + map.MapHeight;
}

function showLoading()
{
	loading.style.left = (document.body.clientWidth/2 - parseInt(loading.style.width) /2 + document.body.scrollLeft)
	loading.style.top = (document.body.clientHeight/2 - parseInt(loading.style.height) /2 + document.body.scrollTop)
	loading.style.visibility = "visible";
}

function init()
{	
	setState("ZOOMIN");
	resizeElements();
	
	divMap.onmousemove = getMouse;
	divMap.onmousedown = mapTool;
	divMap.onmouseup = chkMouseUp;
	divMap.ondblclick = stopLine;
	divMap.onmouseout = clearStatus;
	
	// load first map
	map.Units = mapUnits;
	map.ActiveLayer = activeLayer;
	map.getFirstMap();
	
	//get layers
	var layer = new Layer();
	layer.getSearchableLayers();
	
	// load 'layer labels' drop down
	layer = new Layer();
	layer.getLayerNames();
	
	zs.createHTML();
}

function clearStatus()
{
	window.status = "";
}

function setActiveLayerNoClick(layerPosition)
{
	if( activeLayer )
		eval("lyr" + activeLayer).className = "layerNormal";
		
	eval("lyr" + layerPosition).className = "layerActive";
	map.ActiveLayer = layerPosition;
	activeLayer = layerPosition;
}

function setActiveLayer(layerPosition)
{
	if( event && event.srcElement.tagName == "INPUT" )
		return;
		
	if( activeLayer )
		eval("lyr" + activeLayer).className = "layerNormal";
		
	eval("lyr" + layerPosition).className = "layerActive";
	map.ActiveLayer = layerPosition;
	activeLayer = layerPosition;
}

function changeLayerVisible(layerName)
{
	// find layer in "layerArray" and set its visibility 
	// to the the opposite of its current setting
	var layer;
	
	for( var i = 0; i < layerArray.length; i++ )
	{
		layer = layerArray[i];
		
		if( layer.Name == layerName )
		{
			// found layer, change it's visibility setting
			if( layer.IsVisible )
				layer.IsVisible = false;
			else if( !layer.IsVisible )
				layer.IsVisible = true;
		}
	}
}

function updateVisibleLayers()
{
	showLoading();
	
	// send request to web service to get new map
	map.getMap(state, map.getMinX(), map.getMinY(), map.getMaxX(), map.getMaxY(), false);
}

function getVisibleLayerString()
{
	// take "layerArray" and send request back to server for new list
	// of layers to be visible.  this list also includes spatial filters (aka, cloned layers)
	// ** SymbolField will be null or blank if the default is to be used
	// ?layers=Elevation,true,SymbolField$Polygon,123,345,456,678*ObjectIds,123,23,45,87|Streets...
	var layerString = "";
	var layer;
	
	for( var i = 0; i < layerArray.length; i++ )
	{
		layer = layerArray[i];
		layerString += layer.Name + "," + layer.IsVisible + ",";
		
		if( layer.SymbolField != null && layer.SymbolField != '' )
			layerString += layer.SymbolField;
		
		if( layer.SpatialFilter != null )
		{
			var spatialFilter = layer.SpatialFilter;
			
			if( spatialFilter.Type != null )
			{
				layerString += "$" + spatialFilter.Type + "," + spatialFilter.Points;
			}
			
			// add ObjectIds to end of this string
			if( spatialFilter.ObjectIdArray != null && spatialFilter.ObjectIdArray.length > 0 )
			{
				layerString += "$ObjectIds";
			
				for( var y = 0; y < spatialFilter.ObjectIdArray.length; y++ )
				{
					layerString += "," + spatialFilter.ObjectIdArray[y];
				}
			}
		}
		
		layerString += "|";
	}
	
	// remove last pipe "|" from layerString
	layerString = layerString.substr(0, layerString.lastIndexOf('|'));
	return layerString;
}

function calcScale()
{
	var mapScale = (map.getMaxX() - map.getMinX()) / map.MapWidth * 96; //mapunits/inch
	
	switch(map.Units)
	{
		case 'METERS':
			mapScale = mapScale / 0.0254;
			break;
		
		case 'FEET':
			mapScale = mapScale / 0.0254 * 0.3048;
			break;
		
		case 'MILES':
			mapScale = mapScale / 0.0254 * 0.3048 / 5280;
			break;
	}
	
	map.Scale = mapScale;
}

function checkVisScale()
{
	var chk;
	var layer;
	
	for(var i = 0; i < layerArray.length; i++)
	{
		layer = layerArray[i];
		var layerChk = document.getElementById("chk" + layer.LayerPosition);
		
		// check for "blank" values
		if( (parseFloat(layer.MinScale) == -1.0 || parseFloat(layer.MinScale) <= parseFloat(map.Scale)) 
		  && (parseFloat(layer.MaxScale) == -1.0 || parseFloat(layer.MaxScale) >= parseFloat(map.Scale)) )
		{
			// enable
			layerChk.disabled = false;
		}
		else
		{
			// set chk to disabled
			layerChk.disabled = true;
		}
	}
}

function collapseLayerGroup(group)
{
	event.cancelBubble = true;
	
	if( event.srcElement.src.indexOf('minus') != -1 )
		event.srcElement.src = "images/plus.gif";
	else
		event.srcElement.src = "images/minus.gif";

	for( var i = 0; i < layerArray.length; i++ )
	{
		layer = layerArray[i];
		
		if( layer.LayerGroupName == group )
		{
			if( eval("lyr" + layer.LayerPosition).style.display == 'none' )
				eval("lyr" + layer.LayerPosition).style.display = 'block';
			else
				eval("lyr" + layer.LayerPosition).style.display = 'none';
		}
	}
}

// command: SELECTRECT, SELECTLINE, SELECTPOLY
function spatialSelect(command, points, isZoomTo)
{
	//clear current spatial filters, if necessary
	if( selectMode == 0 )
		clearSelection(false);

	// "clone" active layer (add to SpatialFilter array of layer object in layerArray)
	if( map.ActiveLayer != "" )
	{
		var layer;
		var spatialFilter;
		
		for( var i = 0; i < layerArray.length; i++ )
		{
			layer = layerArray[i];
			
			if( layer.LayerPosition == map.ActiveLayer )
			{
				// set that spatial filter object's "type" and "points"
				spatialFilter = new SpatialFilter();
				spatialFilter.Points = "";
				
				// parse out points array, convert to map units, store in string using ',' to delim
				for( var x = 0; x < points.length; x += 2 )
				{
					var strx = points[x];
					var stry = points[x+1];
					
					if( isZoomTo )
						spatialFilter.Points += strx + "," + stry + ",";
					else
						spatialFilter.Points += convertMapPoints(strx, stry);
				}
				
				spatialFilter.Points = spatialFilter.Points.substr(0, spatialFilter.Points.lastIndexOf(','));
				
				if( command == "SELECTRECT" )
					spatialFilter.Type = "Polygon";
				else if( command == "SELECTLINE" )
					spatialFilter.Type = "Line";
				else if( command == "SELECTPOLY" )
					spatialFilter.Type = "Polygon";
				
				layer.SpatialFilter = spatialFilter;
				break;
			}
		}
		
		// send request for spatial filter data
		spatialFilter.getSpatialFilterResults();
        
		// send request to server using map.getMap() call
		map.getMap(state, map.getMinX(), map.getMinY(), map.getMaxX(), map.getMaxY(), true);
	}
}

function collapseFeatureData(featureID, fieldsLength)
{
	if( event )
	{
		if( event.srcElement.src.indexOf('minus') != -1 )
			event.srcElement.src = "images/plus.gif";
		else
			event.srcElement.src = "images/minus.gif";
	}
	
	for( var i = 0; i < fieldsLength; i++ )
	{
		if( eval(featureID + "field" + i).style.display == 'none' )
			eval(featureID + "field" + i).style.display = 'block';
		else
			eval(featureID + "field" + i).style.display = 'none';
	}
}

function convertMapPoints(x, y)
{
	x = (map.getMinX() * 1) + (x * (map.getMaxX() - map.getMinX())/map.MapWidth);
	y = map.getMaxY() - (y * (map.getMaxY() - map.getMinY())/map.MapHeight);
	
	return x + "," + y + ",";
}

function clearSelection(clearMap)
{
	if( clearMap )
		showLoading();
	
	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(state, map.getMinX(), map.getMinY(), map.getMaxX(), map.getMaxY(), false);
		activateTab("tabLayers");
	}
}

function activateTab(tabID)
{	
	for( var i = 0; i < tblTabs.getElementsByTagName("td").length; i++ )
	{
		id = tblTabs.getElementsByTagName("td")[i].id;
		divid = id.replace("tab","div");
		
		if( id == tabID )
		{
			eval(id).className = "tabActive";
			eval(divid).style.display = "block";
		}
		else
		{
			eval(id).className = "tabNormal";
			eval(divid).style.display = "none";
		}
	}
}

function getGeocode(address,crossStreet, countyList)
{
	var find = new Find();
	
	if( crossStreet != "" )
		address += " @ " + crossStreet;
	
	find.getGeocode(address, countyList, true);
}

function zoomLatLong(lat,lng)
{
	if (parseFloat(lat) > 39.6 || parseFloat(lat) < 36.4){
		alert("Latitude is outside of Virginia");
		return;
	}
	if (parseFloat(lng) < -83.9 || parseFloat(lng) > -75.2){
		alert("Longitude is outside of Virginia");
		return;
	}
	
	var arr = new Array();
	
	arr[0] = calcLCCSP83(mapProj, lat, Math.abs(lng))["east"];
	arr[1] = calcLCCSP83(mapProj, lat, Math.abs(lng))["north"];
	
	//Convert output to map Units.  calcLCCSP83 returns meters
	if (map.Units != "METERS")
	{
		arr[0] = convertDistanceUnits(arr[0],"METERS",map.Units);
		arr[1] = convertDistanceUnits(arr[1],"METERS",map.Units);
	}
	
	minX = arr[0] - zoomTolerance;
	minY = arr[1] - zoomTolerance;
	maxX = arr[0] + parseFloat(zoomTolerance);
	maxY = arr[1] + parseFloat(zoomTolerance);
	
	map.getMap(state, minX, minY, maxX, maxY, true);
}

function zoomToScale(scale)
{
	dx = map.getMaxX() - map.getMinX();
	dy = map.getMaxY() - map.getMinY();
	centerX = map.getMaxX() - dx / 2;
	centerY = map.getMaxY() - dy / 2;
	
	scale = scale / map.Scale;
	
	dx = dx * scale / 2;
	dy = dy * scale / 2;
	
	map.getMap("ZOOMIN", (centerX - dx), (centerY - dy), (centerX + parseFloat(dx)), (centerY + parseFloat(dy)), true)
}

function convertDistanceUnits(inputDistance, inputUnits, outputUnits)
{
	var outputDistance;
	
	//Convert everything to METERS
	switch(inputUnits)
	{
		case "METERS":
			outputDistance = inputDistance;
			break;
		case "FEET":
			outputDistance = inputDistance * 0.3048;
			break;
		case "MILES":
			outputDistance = inputDistance * 5280 * 0.3048;
			break;
		case "INCHES":
			outputDistance = inputDistance / 12 * 0.3048;
			break;		
	}
	
	//Convert METERS to OUTPUT UNITS
	switch(outputUnits)
	{
		case "METERS":
			outputDistance = outputDistance;
			break;
		case "FEET":
			outputDistance = outputDistance / 0.3048;
			break;
		case "MILES":
			outputDistance = outputDistance / 0.3048 / 5280;
			break;
		case "INCHES":
			outputDistance = outputDistance / 0.3048 * 12;
			break;	
	}
	
	return outputDistance;
}

function convertAreaUnits(inputArea, inputUnits, outputUnits)
{
	var outputArea;
	
	//Convert everything to SQUARE METERS
	switch(inputUnits)
	{
		case "METERS":
			outputArea = inputArea;
			break;
		case "FEET":
			outputArea = inputArea * Math.pow(0.3048,2);
			break;
		case "MILES":
			outputArea = inputArea * Math.pow(5280,2) * Math.pow(0.3048,2);
			break;
		case "INCHES":
			outputArea = inputArea / Math.pow(12,2) * Math.pow(0.3048,2);
			break;
		case "ACRES":
			outputArea = inputArea / 0.000247105 ;
			break;
	}
	
	//Convert SQUARE METERS to OUTPUT UNITS
	switch(outputUnits)
	{
		case "METERS":
			outputArea = outputArea;
			break;
		case "FEET":
			outputArea = outputArea / Math.pow(0.3048,2);
			break;
		case "MILES":
			outputArea = outputArea / Math.pow(0.3048,2) / Math.pow(5280,2);
			break;
		case "INCHES":
			outputArea = outputArea / Math.pow(0.3048,2) * Math.pow(12,2);
			break;
		case "ACRES":
			outputArea = outputArea * 0.000247105 ;
			break;	
	}
	
	return outputArea;
}