var sQuote = "'";
var dQuote = '"';

function getInitialMap(){
	getMap("");
}


function getServiceInfo(){
	var axl = '<?xml version="1.0" encoding="UTF-8"?><ARCXML version="1.1">\n<REQUEST>\n<GET_SERVICE_INFO renderer="false" extensions="false" fields="false" />\n</REQUEST>\n</ARCXML>\n';
	http = getHTTPObject();
	if ((http != null)) {
            http.open("POST", url, true);
	    http.onreadystatechange = parseLayers;
	    showLayer('loading');
	    http.send(axl);
  }
}


function parseLayers(){
  if (http.readyState == 4) {
   if (http.status == 200) {
      var result = http.responseText;
      //alert(result);
      getLayers(result); 
      getInitialMap();
   } else alert("Error retreiving data");     
  }  
}

function fixedZoomIn(){
    growEnvelope(0.75);
    var env = '<ENVELOPE minx="' + minx + '" miny="' + miny +'" maxx="' + maxx +'" maxy="' + maxy + '" />';
	getMap(env);
}

function fixedZoomOut(){
	growEnvelope(1.35);
	var env = '<ENVELOPE minx="' + minx + '" miny="' + miny +'" maxx="' + maxx +'" maxy="' + maxy + '" />';
	getMap(env);
}

function ZoomOutPoint(x1,y1){
	growEnvelopeZoomOut(1.35,x1,y1);
	var env = '<ENVELOPE minx="' + minx + '" miny="' + miny +'" maxx="' + maxx +'" maxy="' + maxy + '" />';
	getMap(env);
}

function zoom(left, bottom, right, top){
     if(activeTool == "zoomin") getExtentForZoomIn(left, bottom, right, top);
     else getExtentForZoomOut(left, bottom, right, top);	
     var env = '<ENVELOPE minx="' + minx + '" miny="' + miny +'" maxx="' + maxx +'" maxy="' + maxy + '" />';
     getMap(env);	

}

function pan(ix, iy){
	var dx = (maxx - minx)/mwidth;
	var mx = dx*ix;
	var my = dx*iy;
	minx += mx;
	maxx += mx;
	miny += my;
	maxy += my;
	var env = '<ENVELOPE minx="' + minx + '" miny="' + miny +'" maxx="' + maxx +'" maxy="' + maxy + '" />';
     	getMap(env);
}

function panDirection(dir){
	shift(dir);
	var env = '<ENVELOPE minx="' + minx + '" miny="' + miny +'" maxx="' + maxx +'" maxy="' + maxy + '" />';
     	getMap(env);
}

function shift(dir){
	var dx = maxx - minx;
	var dy = maxy - miny;
		
	switch(dir) {
		//NORTH
		case "north":
			miny += 0.3*dy;
			maxy += 0.3*dy;
		break;
		//south
		case "south":
			miny -= 0.3*dy;
			maxy -= 0.3*dy;
		break;
		//east
		case "east":
			minx += 0.3*dx;
			maxx += 0.3*dx;
		break;
		//west
		case "west":
			minx -= 0.3*dx;
			maxx -= 0.3*dx;
		break;
		//northeast
		case "ne":
			miny += 0.3*dy;
			maxy += 0.3*dy;
			minx += 0.3*dx;
			maxx += 0.3*dx;
		break;
		//northwest
		case "nw":
			miny += 0.3*dy;
			maxy += 0.3*dy;
			minx -= 0.3*dx;
			maxx -= 0.3*dx;
		break;
		//southeast
		case "se":
			miny -= 0.3*dy;
			maxy -= 0.3*dy;
			minx += 0.3*dx;
			maxx += 0.3*dx;
		break;
		//southwest
		case "sw":
			miny -= 0.3*dy;
			maxy -= 0.3*dy;
			minx -= 0.3*dx;
			maxx -= 0.3*dx;
		break
	}
}

function getExtentForZoomIn(left, bottom, right, top){
	var LLPoint = getMapXY(left, bottom);
	minx = LLPoint[0];
	miny = LLPoint[1];
	var URPoint = getMapXY(right, top);
	maxx = URPoint[0];
	maxy = URPoint[1];
}


function getExtentForZoomOut(left, bottom, right, top){
	var xDiff= maxx-minx;
	var yDiff= maxy-miny;

	var pwidth = right-left;
	var pheight = top-bottom;
	var xRatio = mwidth / pwidth;
	var yRatio = mheight / pheight;
	var xAdd = xRatio * xDiff / 2;
	var yAdd = yRatio * yDiff / 2;
	minx =  minx - xAdd;
	maxx = maxx + xAdd;
	miny = miny - yAdd;
	maxy = maxy + yAdd;
}

function getMapXY(xIn,yIn) {
	var newValues = new Array();
	var mouseX = xIn;
	var pixelX = (maxx-minx) / mwidth;
	var newX = pixelX * mouseX + minx;
	var mouseY = mheight - yIn;
	var pixelY = (maxy-miny) / mheight;
	var newY = (pixelY * mouseY) + miny;
	newValues[0] = newX;
	newValues[1] = newY;
	return newValues; 
}

function growEnvelope(value){
	var dx = maxx - minx;
	var dy = maxy - miny;

	var cx = (maxx + minx)/2.0;
	var cy = (maxy + miny)/2.0;

	var dx1 = 0.5 * value * dx;
	var dy1 = 0.5 * value * dy;

	minx = cx - dx1;
	miny = cy - dy1;
	maxx = cx + dx1;
	maxy = cy + dy1;
}

function growEnvelopeZoomOut(value,x1,y1){
	var dx = maxx - minx;
	var dy = maxy - miny;

	var dx1 = 0.5 * value * dx;
	var dy1 = 0.5 * value * dy;

	minx = x1 - dx1;
	miny = y1 - dy1;
	maxx = x1 + dx1;
	maxy = y1 + dy1;
}

function getMapWithCurrentExtent(){
	var env = '<ENVELOPE minx="' + minx + '" miny="' + miny +'" maxx="' + maxx +'" maxy="' + maxy + '" />';
	getMap(env);
}

function getMap(envelope) {
 	http = getHTTPObject();
	if ((http != null)) {
		showLayer('loading');
		var axl;
    		if (showBuffer) {
			axl = getBufferRequest(envelope);
		} else if (showGeocode) {
      			axl = getGeoBufferRequest(envelope);
		} else {
			axl = getMapRequest(envelope);
		}
		http.open("POST", url, true);
		http.onreadystatechange = printResponse;
		http.send(axl);
	}
}

function getBufferMap(envelope) {
  	http = getHTTPObject();
  	if ((http != null)) {
    		var axl = getBufferRequest(envelope);
    		http.open("POST", url, true);
    		http.onreadystatechange = printResponse;
    		showLayer('loading');
    		http.send(axl);
  	}
}

//GEOCODE FUNCTION
function sendGeoQuery(envelope,lc,lc2) {
	getGeoMap("",lc,lc2);
}

function getGeoRequest(env,lcc,lcc2) {
	var theString = '<ARCXML version="1.1">\n<REQUEST>\n<GET_GEOCODE maxcandidates="' + maxGeocodeCandidates + '" minscore="' + minGeocodeScore + '">\n';
	theString += '<LAYER id="'+GeocodeLayerID+'" />';
	theString += '<ADDRESS>\n';
	theString += '<GCTAG id="STREET" value="' + lcc + '"/>\n';
	theString += '<GCTAG id="CROSSSTREET" value="' + lcc2 + '"/>\n';
	theString += '</ADDRESS>\n</GET_GEOCODE>\n</REQUEST>\n</ARCXML>\n';
	return theString;
}

function getGeoMap(envelope,lct,lct2) {
	http = getHTTPObject();
  	if ((http != null)) {
    		var axl;
    		axl = getGeoRequest(envelope,lct,lct2);
    		http.open("POST", imsGeocodeURL, true);
    		http.onreadystatechange = parseGeocode;
    		showLayer('loading');
    		http.send(axl);
  	}
}

function parseGeocode(){
  	if (http.readyState == 4) {
   		if (http.status == 200) {
      			var result = http.responseText;
      			parseGeocodeResults(result);
      			var axl=getGeoBufferRequest("z"); 
      			getGeocodedMap(axl);
   		} else alert("Error retreiving geocoded data");     
  	}  
}

function getGeocodedMap(axl) {
  	http = getHTTPObject();
  	if ((http != null)) {
    		http.open("POST", url, true);
    		http.onreadystatechange = printResponse;
    		showLayer('loading');
    		http.send(axl);
  	}
}

function getMapRequest(envelope){
	var axl = '<?xml version="1.0" encoding="UTF-8"?>\n';
	axl += '<ARCXML version="1.1">\n';
	axl += '<REQUEST>\n';
	axl += '<GET_IMAGE>\n';
	axl += '<PROPERTIES>\n';
	axl += envelope;
	axl += '<IMAGESIZE height="' + mapheight + '" width="' + mapwidth + '" />\n';
	axl += '<LAYERLIST >\n';
	for (var i=0;i<layerCount;i++) {
		if (LayerVisible[i]==1) {
			axl += '<LAYERDEF id="' + LayerID[i] + '" visible="true" />\n';
		}else {
			axl += '<LAYERDEF id="' + LayerID[i] + '" visible="false" />\n';
		}
	}
	axl += '</LAYERLIST>\n';
	axl += '</PROPERTIES>\n';
	axl += '</GET_IMAGE>\n';
	axl += '</REQUEST></ARCXML>';
	return axl;
}

function getBufferRequest(envelope){
	var axl = '<?xml version="1.0" encoding="UTF-8"?>\n';
	axl += '<ARCXML version="1.1">\n';
	axl += '<REQUEST>\n';
	axl += '<GET_IMAGE>\n';
	axl += '<PROPERTIES>\n';
	if (envelope=="z") {
	  axl += '<ENVELOPE minx="' + minx + '" miny="' + miny +'" maxx="' + maxx +'" maxy="' + maxy + '" />\n';
	}else{
	  axl += envelope;
	}
	axl += '<IMAGESIZE height="' + mapheight + '" width="' + mapwidth + '" />\n';
	axl += '<LAYERLIST >\n';
	for (var i=0;i<layerCount;i++) {
		if (LayerVisible[i]==1) {
			axl += '<LAYERDEF id="' + LayerID[i] + '" visible="true" />\n';
		}else {
			axl += '<LAYERDEF id="' + LayerID[i] + '" visible="false" />\n';
		}
	}
	axl += '</LAYERLIST>\n';
	axl += '</PROPERTIES>\n';
	axl += addBufferToMap();
	axl += '</GET_IMAGE>\n';
	axl += '</REQUEST></ARCXML>';
	return axl;
}

function getGeoBufferRequest(envelope){
	var axl = '<?xml version="1.0" encoding="UTF-8"?>\n';
	axl += '<ARCXML version="1.1">\n';
	axl += '<REQUEST>\n';
	axl += '<GET_IMAGE>\n';
	axl += '<PROPERTIES>\n';
	if (envelope=="z") {
	  axl += '<ENVELOPE minx="' + minx + '" miny="' + miny +'" maxx="' + maxx +'" maxy="' + maxy + '" />\n';
	}else{
	  axl += envelope;
	}
	axl += '<IMAGESIZE height="' + mapheight + '" width="' + mapwidth + '" />\n';
	axl += '<LAYERLIST >\n';
	for (var i=0;i<layerCount;i++) {
		if (LayerVisible[i]==1) {
			axl += '<LAYERDEF id="' + LayerID[i] + '" visible="true" />\n';
		}else {
			axl += '<LAYERDEF id="' + LayerID[i] + '" visible="false" />\n';
		}
	}
	axl += '</LAYERLIST>\n';
	axl += '</PROPERTIES>\n';
	axl += addGeocodeBufferToMap();
	axl += '</GET_IMAGE>\n';
	axl += '</REQUEST></ARCXML>';
	return axl;
}

//need to define loadXML function for non IE browser which do not have loadXML implemented
//we use loadXML (can't use load method) to load ArcXML response because the response from ArcIMS is in plain text format   

if(!isIE){
	Document.prototype.loadXML = function (s) {
      
	   	// parse the string to a new doc   
	   	var doc2 = (new DOMParser()).parseFromString(s, "text/xml");
      
	   	// remove all initial children
	   	while (this.hasChildNodes())
	   	   this.removeChild(this.lastChild);
         
	   	// insert and import nodes
	   	for (var i = 0; i < doc2.childNodes.length; i++) {
	   	   this.appendChild(this.importNode(doc2.childNodes[i], true));
	   	}
       };
}

function printResponse(){
	if (http.readyState == 4) {
		if (http.status == 200) {
			var result = http.responseText;
      			var theURL;
			//var result = http.responseXML;  //fails
			//alert(result);
			if (navigator.userAgent.indexOf( 'Safari' ) != -1) {		//no xmlDoc for SAFARI
				theURL = getURL(result);
				parseEnvelope(result, 0);
			} else {
				var xmlDoc;
				if (document.implementation && document.implementation.createDocument) { 
					// MOZILLA 
					xmlDoc = document.implementation.createDocument("", "", null);
      					xmlDoc.async="false";
        				xmlDoc.loadXML(result);
					theURL = xmlDoc.getElementsByTagName("OUTPUT").item(0).getAttribute("url");
				} else if (window.ActiveXObject){
					//IE
					xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
					xmlDoc.async="false";
					xmlDoc.loadXML(result);
					theURL = xmlDoc.getElementsByTagName("OUTPUT").item(0).getAttribute("url");
				}
				var env = xmlDoc.getElementsByTagName("ENVELOPE").item(0);
				minx = parseFloat(env.getAttribute("minx"));
				miny = parseFloat(env.getAttribute("miny"));
				maxx = parseFloat(env.getAttribute("maxx"));
				maxy = parseFloat(env.getAttribute("maxy"));
			}
			document.getElementById('theImage').src = theURL;

			//do not show the report results if only bringing up the initial blank map
			if (!firstQuery) {
				getBufferReport();
			} else {
				sendDateQuery();
			}
			hideLayer('loading');
		} else alert("Error retreiving data"); 
	} 
}

function WriteToFile(bname) {
     var filename = 'c://aatemp.txt';
     var fso = new ActiveXObject('Scripting.FileSystemObject');
     if (fso.FileExists(filename)) {
          var a, ForAppending, file;
          ForAppending = 8;
          file = fso.OpenTextFile(filename, ForAppending, false);
          file.WriteLine(bname);
          }
     else {
          var file = fso.CreateTextFile(filename, true);
          file.WriteLine(bname);
          }
     file.Close();
} 

function getURL(theReply) {
	var theURL = "";
	var startpos = 0;
	var endpos = 0;

	var pos = theReply.indexOf("OUTPUT");
	var pos1 = theReply.indexOf("url", pos);
	pos1 += 5;
	var pos2 = theReply.indexOf("\"", pos1);
	theURL = theReply.substring(pos1,pos2);

	return theURL;
}

function parseEnvelope(theString, startpos) {
	theString = theString.toUpperCase();
	var tempString = "";
	var dQuote="\"";
	var pos = theString.indexOf("ENVELOPE",startpos);
	if (pos!=-1) {
		pos = pos + 8;
		startpos = theString.indexOf("MINX=",pos);
		startpos += 6;
		var endpos = theString.indexOf(dQuote,startpos);
		tempString = theString.substring(startpos,endpos);
		minx = parseFloat(tempString);
		startpos = theString.indexOf("MINY=",pos);
		startpos += 6;
		endpos = theString.indexOf(dQuote,startpos);
		tempString = theString.substring(startpos,endpos);
		miny = parseFloat(tempString);
		startpos = theString.indexOf("MAXX=",pos);
		startpos += 6;
		endpos = theString.indexOf(dQuote,startpos);
		tempString = theString.substring(startpos,endpos);
		maxx = parseFloat(tempString);
		startpos = theString.indexOf("MAXY=",pos);
		startpos += 6;
		endpos = theString.indexOf(dQuote,startpos);
		tempString = theString.substring(startpos,endpos);
		maxy = parseFloat(tempString);

	}

}


var forceCommaInRequest = new Array();
forceCommaInRequest[0] = false;

function forceComma(theNumber) {
	var comma = ",";
	var dot = ".";
	var charOut = comma;
	var charIn = dot;
	var numberString = new String(theNumber);
	if (forceCommaInRequest[0]) {
		charOut = dot;
		charIn = comma;
	}
	var pos = numberString.indexOf(charOut);
	if (pos!=-1) {
		var begin = numberString.substring(0,pos);
		var ending = numberString.substring(pos+1, numberString.length);
		numberString = begin + charIn + ending;
	}
	return numberString;
}

// set number string to have decimal character to match browser language type - point or comma
function setDecimalString(numberString) {
	if (numberString.indexOf(",")!=-1) forceCommaInRequest[0] = true;
	if (decimalChar==".") {
		numberString = numberString.replace(/,/g, ".");
	} else {
		numberString = numberString.replace(/./g, ",");
	}
	return numberString;
}


//DATE OF FILE
function getDateQueryString() {
	var newString = 'CATEGORY = \'SHAPEDATE\'';
	var theString = '<ARCXML version="1.1">\n<REQUEST>\n<GET_FEATURES outputmode="xml" geometry="false" envelope="true" checkesc ="true"';
	theString += ' featurelimit="10" beginrecord="0">\n';
	theString += '<LAYER id="0" />';
	theString += '<SPATIALQUERY subfields="' + selectFields + '" where="' + newString + '" />';
	theString += '</GET_FEATURES>';
	theString += '</REQUEST>';
	theString += '</ARCXML>';
	return theString;
}


function sendDateQuery(){
	var axl = getDateQueryString();
	http = getHTTPObject();
	if ((http != null)) {
            var queryUrl = url + "&CustomService=Query";
            http.open("POST", queryUrl, true);
	    http.onreadystatechange = parseDateString;
	    http.send(axl);
	}
}


function parseDateString(){
  if (http.readyState == 4) {
   if (http.status == 200) {
      var result = http.responseText;
      parseShapeDate(result);
   } else alert("Error retreiving date string");     
  }  
}



// parse layer field value samples
function parseShapeDate(theReply) {
		var pos = 0;
		var startpos = 0;
		var endpos = 0;
		var featureCount = justGetFeatureCount(theReply);
		var tempString="";
		if (featureCount > 0) {
			for (var i=0;i<featureCount;i++) {
				pos = theReply.indexOf(dateField,endpos);
				startpos = pos + 2 + dateField.length;
				endpos =theReply.indexOf('"',startpos);
				lastDate = theReply.substring(startpos,endpos);
			}
			if (lastDate != "" && lastDate != "=") {
				aboutstr1 = "Crime incident information was last updated on " + lastDate + "."
				updateContent("datetitle1","Crime data last updated: "+lastDate);
				updateContent("datetitle2","Crime data last updated: "+lastDate);
				updateContent("datetitle3","Crime data last updated: "+lastDate);
				updateContent("datetitle4","Crime data last updated: "+lastDate);
				updateContent("datetitle5","Crime data last updated: "+lastDate);
				updateContent("datetitle7","Crime data last updated: "+lastDate);
			}
			aboutstr1 += " Locations of incidents on the map are approximate. See the <a href='#' onclick='showPane(document.getElementById(\"tab6\"))'>dislaimer.</a> This application uses map layers from the City of Davis Geographic Information System (GIS), crime data from the Davis Police Department records management system, and ArcIMS map server software. The application was created by the City of Davis Police Department and Information Systems Division."
		} else {
				lastDate="";
		}
}

// get the number of features returned in xml response
function justGetFeatureCount(theReply) {
	var theCount = 0;
	var pos = theReply.indexOf("<FEATURECOUNT");
	if (pos!=-1) {
		var theValue = justGetValue(theReply,'count="',dQuote,pos);
		theCount = parseInt(theValue);	
	}
	return theCount;
}

// just get the interior string from the theReply between preString and postString
//		starting from startpos
function justGetValue(theReply,preString,postString,startpos) {
	var theValue = "";
	var pos = theReply.indexOf(preString,startpos);
	if (pos!=-1) {
		pos = pos + preString.length;
		var endpos = theReply.indexOf(postString,(pos));
		if (endpos!=-1) {
			theValue = theReply.substring(pos,endpos);
			xmlEndPos = endpos;
		}
	}
	return theValue;	
}

//draw a circle around geocoded location at distance
function bufferDrawCircle(){

	var theCoords="";
	var increment=0.0;
	var firstTime=true;
	var distance = bufferDistance;
	if (ScaleBarUnits == "miles")  {
		distance = distance * 5280;
	}

	x = geocodeX;
	y = geocodeY;

	while (increment<=350.0) {
		var x1 = x + (distance * Math.cos(increment*Math.PI/180));
		var y1 = y + (distance * Math.sin(increment*Math.PI/180));
		theCoords=theCoords+String(x1)+" ";
		theCoords=theCoords+String(y1)+";";
		if (firstTime) {
			firstString=theCoords;
			firstTime=false;
		}
		increment=increment+10;
	}
	var lastString = firstString.substring(0,firstString.length - 1)
	//alert(lastString);
	theCoords=theCoords+lastString;

	// ArcXML to draw circle object
	var theString = '<OBJECT units="database">\n';
	theString += '<POLYGON coords="'+theCoords+'">\n';
	theString += '<SIMPLEPOLYGONSYMBOL fillcolor="'+selectColor+'" filltype="solid" filltransparency="0.4" boundarywidth="4" boundarytransparency="0.5" boundarycolor="255,51,102" />\n';
	theString += '</POLYGON>\n';
	theString += '</OBJECT>\n';
	return theString;
}