var oXHR_instances = new Object();
var iXHR = 0;

var aXHR_IDs = new Array('a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r');
/* @public
 * @returns a unique id from the aXHR_IDs array for a XML HTTP Request
 * @type string
 */
function xhr_getID() {
	return aXHR_IDs.shift();
}
/* @public
 * @returns true/false on successful addition of the ID back to the aXHR_IDs array
 * @type Boolean
 */
function xhr_done(id) {
	if (id == null) {
		return false;
	} else if (parseInt(id, 10) == parseFloat(id, 10)) {
		// is an integer then continue
	} else {
		if (aXHR_IDs.push(id) == -1) {
			return false;
		}
	}
	this.oXHR_instances[id] = null;
    iXHR--;
	return true;
}
function xhr_create_instance(id) {
	//
	var temp = null;
	if (this.oXHR_instances[id] &&
	this.oXHR_instances[id] != null) {
		return this.oXHR_instances[id];
	}
	temp = getHTTPObject();
	this.oXHR_instances[id] = temp;
	iXHR += 1;
	return temp;
}


function getInitialMap(){
	getMap("", true);
}

function getServiceInfo(){
    debug("aimsXML.js: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';
	// get id from global xhr_ids
	var id = xhr_getID();
	var xhr = xhr_create_instance(id);
	//if ((http != null) && (!isWorking)) {
	if ((xhr != null)) {

	    xhr.open("POST", url, true);
	    debug("aimsXML.js:getServiceInfo:xhr.open");
	    xhr.onreadystatechange = function(){
	    	parseLayers(id);
	    };
	    debug("aimsXML.js:getServiceInfo:xhr.onreadystatechange");
	    isWorking = true;
	    showLayer('loading');
	    debug("AXL="+axl);
	    xhr.send(axl);
  }
}

function parseLayers(id){
  var xhr = xhr_create_instance(id);
  if (xhr.readyState == 4) {
  
   if (xhr.status == 200) {
      debug("aimsXML.js:parseLayers:xhr.status");
      var result = xhr.responseText;
      debug("aimsXML.js:parseLayers:xhr.responseText");
      xhr_done(id);
      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, true);
}

function fixedZoomOut(){
	growEnvelope(1.25);
	var env = '<ENVELOPE minx="' + minx + '" miny="' + miny +'" maxx="' + maxx +'" maxy="' + maxy + '" />';
	getMap(env, true);
}
function zoom(left, bottom, right, top){
     if(activeTool == "zoomin") {
     	getExtentForZoomIn(left, bottom, right, top);
     } else {
     	var tmpMinMax = getExtentForZoomOut(left, bottom, right, top);
     	minx = tmpMinMax[0];
     	miny = tmpMinMax[1];
     	maxx = tmpMinMax[2];
     	maxy = tmpMinMax[3];
     	debug("after getExtentForZoomOut: "+minx+","+miny+","+maxx+","+maxy);
     }
     var env = '<ENVELOPE minx="' + minx + '" miny="' + miny +'" maxx="' + maxx +'" maxy="' + maxy + '" />';
     getMap(env, true);
}
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 tmpMinMax = adjust_min_max("pan",minx,miny,maxx,maxy);
	minx = tmpMinMax[0];
	miny = tmpMinMax[1];
	maxx = tmpMinMax[2];
	maxy = tmpMinMax[3];
	var env = '<ENVELOPE minx="' + minx + '" miny="' + miny +'" maxx="' + maxx +'" maxy="' + maxy + '" />';
    getMap(env, true);
}
function panDirection(dir){
	shift(dir);
	var tmpMinMax = adjust_min_max("pan",minx,miny,maxx,maxy);
	minx = tmpMinMax[0];
	miny = tmpMinMax[1];
	maxx = tmpMinMax[2];
	maxy = tmpMinMax[3];
	var env = '<ENVELOPE minx="' + minx + '" miny="' + miny +'" maxx="' + maxx +'" maxy="' + maxy + '" />';
    getMap(env, true);
}

function shift(dir){
	var dx = maxx - minx;
	var dy = maxy - miny;
		
	switch(dir) {
		//NORTH
		case "north":
			miny += fShift_amt * dy;
			maxy += fShift_amt * dy;
		break;
		//south
		case "south":
			miny -= fShift_amt * dy;
			maxy -= fShift_amt * dy;
		break;
		//east
		case "east":
			minx += fShift_amt * dx;
			maxx += fShift_amt * dx;
		break;
		//west
		case "west":
			minx -= fShift_amt * dx;
			maxx -= fShift_amt * dx;
		break;
		//northeast
		case "ne":
			miny += fShift_amt * dy;
			maxy += fShift_amt * dy;
			minx += fShift_amt * dx;
			maxx += fShift_amt * dx;
		break;
		//northwest
		case "nw":
			miny += fShift_amt * dy;
			maxy += fShift_amt * dy;
			minx -= fShift_amt * dx;
			maxx -= fShift_amt * dx;
		break;
		//southeast
		case "se":
			miny -= fShift_amt * dy;
			maxy -= fShift_amt * dy;
			minx += fShift_amt * dx;
			maxx += fShift_amt * dx;
		break;
		//southwest
		case "sw":
			miny -= fShift_amt * dy;
			maxy -= fShift_amt * dy;
			minx -= fShift_amt * dx;
			maxx -= fShift_amt * dx;
		break
	}
}

function getExtentForZoomIn(tmpLeft, tmpBottom, tmpRight, tmpTop){
	/* added 20060515 the following additional computations
	 * basically padding the selected zoom area
	 * (xHalf / zoomFactor) and
	 * (yHalf / zoomFactor)
	 */
	var LLPoint = getMapXY(tmpLeft, tmpBottom);
	var URPoint = getMapXY(tmpRight, tmpTop);
	if (zoomFactor == 0) {
		minx = LLPoint[0];
		miny = LLPoint[1];
		maxx = URPoint[0];
		maxy = URPoint[1];
	} else {
		minx = LLPoint[0] - xHalf/zoomFactor;
		miny = LLPoint[1] - yHalf/zoomFactor;
		maxx = URPoint[0] + xHalf/zoomFactor;
		maxy = URPoint[1] + yHalf/zoomFactor;
	}
	debug("getExtentForZoomIn:left("+tmpLeft+"), bottom("+tmpBottom+"), right("+tmpRight+"), top("+tmpTop+")");
	debug("getExtentForZoomIn:minx("+minx+"), miny("+miny+"), maxx("+maxx+"), maxy("+maxy+")");
}


function getExtentForZoomOut(tmpLeft, tmpBottom, tmpRight, tmpTop) {
	debug("before getExtentForZoomOut: minx="+minx+",miny="+miny+"maxx="+maxx+",maxy="+maxy);
	var pwidth = tmpRight - tmpLeft;
	var pheight = tmpTop - tmpBottom;
	debug("getExtentForZoomOut: mwidth="+mwidth+", mheight="+mheight);
	var xRatio = mwidth / pwidth;
	var yRatio = mheight / pheight;
	var sTmpHeight = Element.getStyle('header','height');
	pos_px = sTmpHeight.indexOf("px");
    var iTmpHeight = parseFloat(sTmpHeight.substring(0,pos_px));
    iTmpHeight = parseInt(iTmpHeight);
	var tmpHeader = getMapXY(0, iTmpHeight);
	debug("getExtentForZoomOut: tmpHeader[1]="+tmpHeader[1]+", maxy="+maxy);
	if (zoomFactor == 0) {
		var xAdd = xRatio * xHalf / 2;
		var yAdd = yRatio * (yHalf + (maxy - tmpHeader[1])) / 2;
	} else {
		var xAdd = xRatio * xHalf / zoomFactor;
		var yAdd = yRatio * (yHalf + (maxy - tmpHeader[1])) / zoomFactor;
	}
	debug('xAdd='+xAdd+', yAdd='+yAdd, minx);
	return adjust_min_max("zoomout", minx - xAdd, miny - yAdd, maxx + xAdd, maxy + yAdd);	
}
function adjust_min_max(sTmpDo,iMinx,iMiny,iMaxx,iMaxy) {
	/* adjusts minx, miny, maxx, maxy
	 * to see if they are past the maps extents/limits
	 */
	var sTmpHeight = Element.getStyle('header','height');
	pos_px = sTmpHeight.indexOf("px");
    var iTmpHeight = parseFloat(sTmpHeight.substring(0,pos_px));
    iTmpHeight = parseInt(iTmpHeight);
	var tmpHeader = getMapXY(0, iTmpHeight);
	if ((iMinx < minX_limit) || (iMinx > maxX_limit)) {
		debug("adjust_min_max:Adjusted iMinx from "+minx+" to ");
		if (sTmpDo == "zoomout") {
			iMinx = minX_limit - xHalf / (zoomFactor == 0?2:zoomFactor);
		} else {
			iMinx = minX_limit;
		}
		debug("new iMinx = "+iMinx);
	}
	if ((iMaxx > maxX_limit) || (iMaxx < minX_limit)) {
		debug("adjust_min_max:Adjusted iMaxx from "+maxx+" to ");
		if (sTmpDo == "zoomout") {
			iMaxx = maxX_limit + xHalf / (zoomFactor == 0?2:zoomFactor);
		} else {
			iMaxx = maxX_limit;
		}
		debug("new iMaxx = "+iMaxx);
	}
	if ((iMiny < minY_limit) || (iMiny > maxY_limit)) {
		debug("adjust_min_max:Adjusted iMiny from "+miny+" to ");
		if (sTmpDo == "zoomout") {
			iMiny = minY_limit - (yHalf) / (zoomFactor == 0?2:zoomFactor);
		} else {
			iMiny = minY_limit;
		}
		debug("new iMiny = "+iMiny);
	}
	if ((iMaxy > maxY_limit) || (iMaxy < minY_limit)) {
		debug("adjust_min_max:Adjusted iMaxy from "+maxy+" to ");
		if (sTmpDo == "zoomout") {
			//iMaxy = maxY_limit + (yHalf + 2 * (iMaxy - tmpHeader[1])) / (zoomFactor == 0?2:zoomFactor);
			iMaxy = maxY_limit + (yHalf) / (zoomFactor == 0?2:zoomFactor);
		} else {
			iMaxy = maxY_limit;
		}
		debug("new iMaxy = "+iMaxy);
	}
	return new Array(iMinx,iMiny,iMaxx,iMaxy);
}
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;
	
	debug('xIn('+xIn+'),'+'pixelX('+pixelX+'),'+'mwidth('+mwidth+'),'+'newX('+newX+')');
	debug('yIn('+yIn+'),'+'pixelY('+pixelY+'),'+'mheight('+mheight+'),'+'newY('+newY+')');
	createHotSpot(
	        xIn+'_'+yIn,
	        xIn,
	        yIn,
	        newX + '_' + newY,
	        bPointDebug
	        );
	convert_latitude_longitude(newX,newY);
	
	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 getMapWithCurrentExtent(tmp_bPointsRefresh){
	tmp_bPointsRefresh = (tmp_bPointsRefresh == null?true:tmp_bPointsRefresh);
	var env = '<ENVELOPE minx="' + minx + '" miny="' + miny +'" maxx="' + maxx +'" maxy="' + maxy + '" />';
	getMap(env, tmp_bPointsRefresh);
}

function getMap(envelope, tmp_bPointsRefresh) {
	// get id from global xhr_ids
    showLayer('loading');
    bPointsRefresh = tmp_bPointsRefresh; // boolean refresh the points?
	var id = xhr_getID();
	var xhr = xhr_create_instance(id);
    if ((xhr != null)) {
    var axl = getMapRequest(envelope);
    debug("map axl="+axl);
    if(!isIE){xhr.overrideMimeType("text/xml")}
    xhr.open("POST", url, true);
    xhr.onreadystatechange = function() {
    	printResponse(id);
    }
     //alert("sending :" + axl);
    
    xhr.send(axl);
    vAXL_screen = axl;
  }
}

function getMapRequest(envelope){
	var axl = '<?xml version="1.0" encoding="UTF-8"?>';
	axl += '<ARCXML version="1.1">';
	axl += ' <REQUEST>';
	axl += '    <GET_IMAGE>';
	axl +=  '    <PROPERTIES>';
	axl += envelope;
	axl += '<IMAGESIZE height="' + mheight + '" width="' + mwidth + '" />';
	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>';
	// geocoding or point with label
	if (showGeocode) {
		axl += geocode;
	}
	axl += '    </GET_IMAGE> </REQUEST></ARCXML>';
	//$('view_axl').innerHTML = 'map '+xml_to_html(axl);
	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
		debug("Starting loadXML");
		var doc2 = (new DOMParser()).parseFromString(s, "text/xml");
		
		/*
			var parser = new DOMParser();
			var doc = parser.parseFromString(xmlhttp.responseText,"application/xml");
			*/
		
		
		debug("loadXML: doc2");

		// remove all initial children
		while (this.hasChildNodes())
		this.removeChild(this.lastChild);
		debug("loadXML: while: removeChild");

		// insert and import nodes
		for (var i = 0; i < doc2.childNodes.length; i++) {
			this.appendChild(this.importNode(doc2.childNodes[i], true));
			debug("loadXML: while: for: appendChild");
		}
	};
}

function geocodeGenerate(tmpID, tmpLabel, tmpX, tmpY, tmpPointColor, tmpPointSize, tmpFontColor, tmpGlow) {
	// draw the point . . . also used to display any point with a label on map
	var sTmp='';
	sTmp += '<LAYER type="acetate" name="geocode_'+tmpID+'">\n';
	//sTmp += '<OBJECT units="database">\n<POINT coords="' + tmpX + coordsDelimiter + tmpY + '">\n';
	//sTmp += '<SIMPLEMARKERSYMBOL type="circle" color="' + tmpPointColor + '" width="' + tmpPointSize +'" outline="255,255,255" overlap="false" />';
	//sTmp += '<RASTERMARKERSYMBOL overlap="true" url="http://maps.cattco.org/website/tourism/graphics/marker_test.gif" image="C:\ArcIMS\Website\tourism\graphics\marker_test.gif" transparency="1.0" antialiasing="false" />';
	//sTmp += '\n</POINT></OBJECT>\n';
	
	//if (geocodeLabel!="") {
	sTmp += '<OBJECT units="database">\n<TEXT coords="' + tmpX + coordsDelimiter + tmpY + '" label="' + tmpLabel + '">\n';
	sTmp += '<TEXTMARKERSYMBOL fontcolor="' + tmpFontColor + '" glowing="'+tmpGlow+'" fontsize="22" halignment="center" valignment="center" overlap="false" outline="0,0,0" antialiasing="True" /></TEXT></OBJECT>\n';
		/* glowing="255,255,255" shadow="196,223,155" */
	//}
	sTmp += '</LAYER>\n';
	return sTmp;
}

function printResponse(id) {
	var xhr = xhr_create_instance(id);
	if (xhr.readyState == 4) {
		//alert(xhr.responseText);
		if (xhr.status == 200) {

			isWorking = false;
			var result = xhr.responseText;
			// alert(xhr.responseText);
			
			/*
			var xmlDoc;
			xmlDoc = xhr.responseXML;
			alert(typeof(xmlDoc));
			//alert(typeof(xmlDoc)+" "+xhr.GetResponseHeader("Content-Type"));
			//  || xhr.GetResponseHeader("Content-Type") != "text/xml"
			if (typeof(xmlDoc) != "object") {
				result = xhr.responseText;
				//xmlDoc.loadXML(result);
			} else {
				result = xhr.responseXML;
			}
			*/
			xhr_done(id); // xhr and id

			if(document.implementation && document.implementation.createDocument) {
				// Mozilla and Opera
				xmlDoc = document.implementation.createDocument("", "", null);
				xmlDoc.async="false";
				//info("Response Header: "+http.GetResponseHeader("Content-Type"));
				info("Result = "+result);
				xmlDoc.loadXML(result);

				debug("completed xmlDoc.loadXML");
			} else if (window.ActiveXObject){
				//IE
				xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
				xmlDoc.async="false";
				xmlDoc.loadXML(result);
			}

			//debug("Result:"+result);
			//  alert(xmlDoc.getElementsByTagName("OUTPUT").item(0).getAttribute("url"));
			var theURL = xmlDoc.getElementsByTagName("OUTPUT").item(0).getAttribute("url");
			var sTmpImage = $('theImage').src;

			// check if this is not the first map
			if (sTmpImage.search(/images\/pixel.gif/gi) == -1) {
				// *** effect ***
				$('contain_image_temp').style.opacity = 1.0;

				// fade tmp_image
				new Effect.Opacity ('contain_image_temp',
				{ duration: 1.0,
				transition: Effect.Transitions.linear,
				from: 1.0, to: 0.0,
				beforeStart:function(){
					$('tmp_image').src = sTmpImage; // assign old Map to tmp image
					// make sure that the temp image container is above the new image
					$('contain_image_temp').style.zIndex = parseInt(Element.getStyle('contain_image_temp','z-index'))+1;
					$('contain_image').style.zIndex = parseInt(Element.getStyle('contain_image','z-index'))-1;
					$('theImage').src = theURL;
					//alert('done');
				},
				afterFinish:function(){
					//alert('Opacity:afterFinish');
					$('contain_image_temp').style.zIndex = parseInt(Element.getStyle('contain_image_temp','z-index'))-1;
					$('contain_image').style.zIndex = parseInt(Element.getStyle('contain_image','z-index'))+1;
					$('contain_image_temp').style.opacity = 1;
				}
				}
				);

			} else {
				$('theImage').src = theURL;
			}

			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"));
			//alert(minx +","+ miny +","+ maxx+","+maxy);
			xHalf = (maxx-minx) / 2;
			yHalf = (maxy-miny) / 2;
			
			//alert(result + " received");
			// parseEnvelope(result, 0);
			// var theURL = getURL(result);
			//document.getElementById('theImage').src = theURL;
			// hide loading layer
			hideLayer('loading');
			
			if (bPointsRefresh) {
				//showLayer('loading');
				bPointsRefresh = false; // set it to false
				em_getPoints();
				
			}
			
		} else { alert("Error retreiving data"); }
	}
}

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);
	}
}

function zoom_test(){
	/*
	reference envelope values minx, miny, maxx, maxy
	limitTop = miny
	limitRight = maxx
	limitBottom = maxy
	limitLeft = minx
    mtop;
    mright;
    mbottom;
    mleft;
    mwidth
    mheight
    */
	alert("Limits: Top(miny)="+miny+", Right(maxx)="+maxx+", Bottom(maxy)="+maxy+", Left(minx)="+minx);
	/*
	var imgW2HRatio = mwidth / mheight;
	var imgH2WRatio = mheight / mwidth;
	var itWidth = limitRight - limitLeft;
	var itHeight = limitTop - limitBottom;
	var mapRatio = itHeight / itWidth;
	var ix = limitLeft + (itWidth/2);
	var iy = limitBottom + (itHeight/2);
	var iSize = itWidth/2;
	if (mwidth>=mheight) {
		//alert("Image wider than tall");
		if (imgH2WRatio<mapRatio) {
			//alert("Map ratio greater than Image" );
			iSize = (itHeight * imgW2HRatio) / 2;
			limitRight = ix + iSize;
			limitLeft = ix - iSize;
		} else {
			//alert("Limit wider than tall");
			iSize = (itWidth * imgH2WRatio) / 2;
			limitTop = iy + iSize;
			limitBottom = iy - iSize;
		}
	} else {
		//alert("Image taller than wide");
		if (imgH2WRatio<mapRatio) {
			//alert("Map ratio greater than Image");
			iSize = (itHeight * imgH2WRatio) / 2;
			limitRight = ix + iSize;
			limitLeft = ix - iSize;
		} else {
			//alert("Map ratio smaller than Image");
			iSize = (itWidth * imgH2WRatio) / 2;
			limitTop = iy + iSize;
			limitBottom = iy - iSize;
		}
	}
	//alert("Adjusted Limits: " + limitLeft + ", " + limitBottom + ", " + limitRight + ", " + limitTop);
	imageLimitLeft=limitLeft;
	imageLimitRight=limitRight;
	imageLimitTop=limitTop
	imageLimitBottom=limitBottom;
	fullLeft = limitLeft;
	fullRight = limitRight;
	fullTop = limitTop;
	fullBottom = limitBottom;

	fullWidth = Math.abs(fullRight - fullLeft);
	fullHeight = Math.abs(fullTop - fullBottom);
	*/
}