// aimsCustom.js
/*
*  JavaScript template file for ArcIMS HTML Viewer
*		dependent on aimsXML.js, ArcIMSparam.js, aimsCommon.js, aimsMap.js,
*		aimsLayers.js, aimsDHTML.js
*		aimsClick.js, aimsNavigation.js,
*/

// brb -- added for zoom to parcels
	var prevActiveLayerIndex;
// brb -- added to allow the default to be used with user
	var theLabelString = "";
	var currRenderLayer;
// global variables

	aimsCustomPresent=true;
	// change these to send XML response to custom function.
	// use numbers >= 1000 and match in useCustomFunction()
	// defaults are defined in aimsXML.js and use standard functions
	
	// xml response mode for selection
	selectXMLMode = 6;
	// xml response mode for identify
	identifyXMLMode = 7;
	// xml response mode for query
	queryXMLMode = 8;
	// xml response mode for find
	findXMLMode = 14;
	// xml response mode hyperlink
	hyperlinkXMLMode = 15;




// custom function for handling clicks 
// 		flow redirected here when
//		toolMode set to >=1000
function customMapTool(e) {
				if (toolMode == 1001) {
						// insert code here
						return false;
				}
				if (toolMode == 1002) {
						// insert code here
				}
				if (toolMode == 1004) {
					getParametersForDownload(e);
				}
				if (toolMode == 1006) {
					getRasterParameters(e);
				}
				//space holder for toolMode == 1007.  It is for zooming to a layer other 
				//than the active layer.  1007 is used in useCustomeFunction()
}

// send  XML response to custom function
//		flow  redirected here when
//		XMLMode >=1000
function useCustomFunction(theReply) {
	if (XMLMode==1001) {
		// insert code here
	} else if (XMLMode==1002) {
		// insert code here
	} else if (XMLMode==1004) {
		processDownloadRequests(theReply);
	} else if (XMLMode==1005) {
		writeCapturePage(theReply);
	} else if (XMLMode==1006) {
		setPixelValue(theReply);
	} else if (XMLMode==1007) {
		zoomToParcel(theReply);
	} else if (XMLMode==1098) {
		//This routine is stored in AppNameXXX_custom.js in each application's javascript directory.
		//This would only be used if you want to apply labels to more than one layer at a time.
		changeRendering(theReply);
	} else if (XMLMode==1099) {
		processRenderingReply(theReply);
	} else if (XMLMode==1010) {
		parent.TOCFrame.customLegend(theReply);
	} else if (XMLMode==1011) {
		showModel(theReply);
	} else if (XMLMode==1012) {
		showTimeSeries(theReply);
	} else if (XMLMode==1111) {
		processZTFReply(theReply);
	} else {
		alert(msgList[55] + XMLMode + msgList[56]);
	}
//	hideLayer("LoadData");
}

// add custom stuff to Map XML request. . . between selection and geocode
function addCustomToMap1(){
	var customString = "";
	/*
		customString += '<LAYER type="ACETATE" name="theMode">\n';
		customString += '<OBJECT units="PIXEL">\n<TEXT coord="5,' + (iHeight-10) + '" label="This is a test">\n';
		customString += '<TEXTMARKERSYMBOL fontstyle="BOLD" fontsize="12" font="ARIAL" fontcolor="' + modeMapColor + '" ';
		customString += 'threed="TRUE" glowing="' + modeMapGlow + '" />\n</TEXT>\n</OBJECT>';
		customString += '\n</LAYER>\n';
	*/
	return customString;
}

// add custom stuff to Map XML request. . . between clickpoints and copyright
function addCustomToMap2(){
	var customString = "";
	
	return customString;
}

// add custom stuff to Map XML request. . . under modeOnMap
function addCustomToMap3(){
	var customString = "";
		/*
		customString += '<LAYER type="ACETATE" name="theMode">\n';
		customString += '<OBJECT units="PIXEL">\n<TEXT coord="5,' + (iHeight-10) + '" label="This is a test">\n';
		customString += '<TEXTMARKERSYMBOL fontstyle="BOLD" fontsize="12" font="ARIAL" fontcolor="' + modeMapColor + '" ';
		customString += 'threed="TRUE" glowing="' + modeMapGlow + '" />\n</TEXT>\n</OBJECT>';
		customString += '\n</LAYER>\n';
		alert(customString);
		*/
	return customString;
}

// add custom stuff to Map XML request. . . on top of everything
function addCustomToMap4(){
	var customString = "";
	
	return customString;
}

// extract layers to download
function extractIt() {
	hideLayer("measureBox");
	alert(msgList[51]);
}

//======================================================================================================================================
// brb -- added to allow users to change rendering
//======================================================================================================================================
function processRenderingReply(theReply) {
	var theLayerID = ClassRenderLayer[currRenderLayer];
	var axlString = getDefaultRendererString(theLayerID, theReply);
	if (axlString == "") {
		return false;
	}
	if (theLabelString == "") {	//this is necessary to get imagetransparency to work...
		axlString = '<GROUPRENDERER>\n' + axlString + theLabelString + '</GROUPRENDERER>';
	}
	ClassRenderString[currRenderLayer] = axlString;
	parent.TOCFrame.updateLayers('refresh');
}

function requestDefaultRendering() {
	var qryString;
	qryString = '<ARCXML version="1.1"><REQUEST>';
	qryString = qryString  + '<GET_SERVICE_INFO fields="false" envelope="false" extension="false" renderer="true"/>';
	qryString = qryString  + '</REQUEST></ARCXML>';
	sendToServer(imsURL,qryString,1099);
}

function getDefaultRendererString(theLayerID, theReply) {
	var nStrt;
	var nEnd;
	var sLayerInfo;
	var sID;
	nStrt = 0;
	//Locate the layer ID in the LAYERINFO string.
	sID = 'id="' + theLayerID;
	nStrt = theReply.indexOf(sID,nStrt);
	if (nStrt < 1) {
		return "";
	}
	//Grab all of the contents of the reply between the end of the FCLASS tag and the end of the LAYERINFO tag...this is the default render string.
	nStrt = findBefore(theReply,"<LAYERINFO",nStrt);
	if (nStrt < 1) {
		return "";
	}
	nStrt = theReply.indexOf('</FCLASS>',nStrt);
	nStrt = nStrt + 9;	//add length of '</FCLASS>'
	nEnd = theReply.indexOf('</LAYERINFO',nStrt);
	if (nEnd < 1) {
		return "";
	} else {
		sLayerInfo = theReply.substr(nStrt, (nEnd-nStrt));
	}
	return sLayerInfo;
}

function composeLabelString(theLayerID, theFontName, theFontSize, theFontColor, theFontStyle, theGlowOption) {
	var j=-1;
	for (var k=0;k<ClassRenderLayer.length;k++) {
		if (ClassRenderLayer[k]==theLayerID) {
			j=k;
			break;
		}
	}
	currRenderLayer = j;

	var theLabel = "";
	for (k=0;k<layerCount;k++) {
		if (theLayerID == LayerID[k]) {
			theLabel = labelField[k];
			break;
		}
	}

	var  theLabelString = '<SIMPLELABELRENDERER field="' + theLabel + '" labelpriorities="1,2,2,4,5,3,2,4">\n';
	if (theFontName == "") {
		theLabelString = theLabelString + '<TEXTSYMBOL antialiasing="true" font="arial" ';
	} else {
		theLabelString = theLabelString + '<TEXTSYMBOL antialiasing="true" font="'+theFontName+'" ';
	}
	if (parseInt(theFontSize) < 1) {
		theLabelString = theLabelString + 'fontsize="12" ';
	} else {
		theLabelString = theLabelString + 'fontsize="'+theFontSize+'" ';
	}
	if (theFontColor == "") {
		theLabelString = theLabelString + 'fontcolor="0,0,0" ';
	} else {
		theLabelString = theLabelString + 'fontcolor="'+theFontColor+'" ';
	}
	theLabelString = theLabelString + 'fontstyle="'+theFontStyle+'" ';
	if (theGlowOption == "gray") {
		theLabelString = theLabelString + 'glowing="128,128,128" ';
	} else if (theGlowOption == "white") {
		theLabelString = theLabelString + 'glowing="255,255,255" ';
	}
	theLabelString = theLabelString + ' />\n</SIMPLELABELRENDERER>\n';
	return theLabelString;
}

//This is really cool, but sometimes it takes a really long time to reverse 10,000 character string...so I won't use it.
//from http://www.webdeveloper.com/forum/archive/index.php/t-4766.html
function findBefore(string,x,y) {
/*	var reversed = reverse(string);
	var backindex = reversed.indexOf(reverse(x),(string.length-y)) + x.length;
	var fixindex = string.length - backindex;
	return fixindex;
*/
	var nStrt;
	var newStart = y - 100;
	nStrt = string.indexOf(x,newStart);
	if (nStrt < 1) {	//if not found...go a little farther back
		var newStart = y - 150;
		nStrt = string.indexOf(x,newStart);
		if (nStrt < 1) {	//if not found...go a little farther back
			return nStrt;
		}
		fixindex = newStart + x.length;
	} else {
		fixindex = newStart + x.length;
	}

	return fixindex;
}

function reverse(string) {
	var newstr = '';
	for (var loop = 1; loop <= string.length; loop++) {
		newstr += string.charAt(string.length-loop);
	}
	return newstr;
}
		
//======================================================================================================================================
//======================================================================================================================================
// added for scale-bar
var screenWidthInches;
var ppi; 
var screenWidthPixels = screen.width;

function promptRatio(){

	screenWidthInches = "12";
	ppi = screenWidthPixels/screenWidthInches;
	parent.TextFrame.document.location= appDir + "ratioForm.htm";

}

function calcNewScale(ratioValue, resolution){
		
	ppi = screenWidthPixels/resolution;
	
	newScaleFactor = ratioValue / (ppi * 39.3701);
	mapScaleFactor = newScaleFactor;

	muWidth = Math.abs(eLeft - eRight);
	muHeight = Math.abs(eBottom - eTop);

	newWidth = (newScaleFactor * iWidth);
	newHeight = (newScaleFactor * iHeight);

	changeWidth = (newWidth - muWidth)/2;
	changeHeight = (newHeight - muHeight)/2;
	
	eBottom = eBottom - changeHeight;
	eTop = eTop + changeHeight;
	eLeft = eLeft - changeWidth;
	eRight = eRight + changeWidth;

	var theNewString = writeXML();
	sendToServer(imsURL, theNewString, 1);

}

// The code below this line pertains to zooming to parcels in the FloodHazard applicstion
// Eventually, the routines will be changed to check a variable to see what layer to zoom to (may or may not be active layer...may be inactive)

// send find request -- this mimics the getFind() routine in aimsQuery.js
function getSpecialFind(theValue) {
//	alert(theValue);
	selectCount=0;
	showBuffer=false;
	highlightedOne="";
	selectPoints.length=0;
	selectLeft.length=0;
	selectRight.length=0;
	selectTop.length=0;
	selectBottom.length=0;
	drawSelectBoundary=false;
	showGeocode=false;
	clickCount=0;
	totalMeasure=0;
	currentMeasure=0;
	selectionMode=1;
	var theNewQueryString = "";
	var theTempString = "";

//alert('heading for getLayerIndex()');
	indx = getLayerIndex('Tax Parcels');
//alert('retrieve theValue and index -- ' + theValue + ' -- ' + indx);

	//save the current active layer index and replace it with our "target" layer
	prevActiveLayerIndex = ActiveLayerIndex;
	ActiveLayerIndex = indx;
	setLayerFields(ActiveLayerIndex);
	var fieldListString = LayerIDField[indx] + " " + LayerShapeField[indx];
//alert('fieldListString=' + fieldListString);
	var elemCount = 0;
//alert('LayerFields.length=' + LayerFields.length);
	for (var i=0;i<LayerFields.length;i++) {
//alert('i=' + i + '; LayerFieldType[i]=' + LayerFieldType[i]);
		if (LayerFieldType[i].indexOf("12",0)!=-1) {
			theTempString = "(" + LayerFields[i] + " LIKE '%" + theValue + "%')";
//alert('theTempString=' + theTempString);
			if (elemCount>0) theTempString = " OR " + theTempString;
			if (theNewQueryString.length + theTempString.length < 1024) {
				theNewQueryString = theNewQueryString + theTempString;
				fieldListString = fieldListString + " " + LayerFields[i];
				elemCount += 1;
			}
			
		}
	}


//======================================================================================================================================
//YOU MUST USE APOSTROPHES, NOT QUOTES TO DELINEATE THE VALUE because this string will be put inside quotes in writeSpecialFindRequest()
//======================================================================================================================================
//works    theNewQueryString = "(STATE01.GISPROD.ADATAXLOTS.PIN LIKE '%" + theValue + "%')";
//works    theNewQueryString = "(UPPER(STATE01.GISPROD.ADATAXLOTS.PIN) LIKE UPPER('%" + theValue + "%'))";
theNewQueryString = "(UPPER(STATE01.GISPROD.ADATAXLOTS.PIN) = UPPER('" + theValue + "'))";
	if (theNewQueryString!="") {
		showRetrieveData();
		showBuffer=false;
		theNewQueryString=makeXMLsafe(theNewQueryString);
		setQueryString = theNewQueryString;
		//alert(theNewQueryString);
		//alert('calling writeSpecialFindRequest');
		var theString = writeSpecialFindRequest(theNewQueryString,fieldListString);
		//alert('sending to server');
		sendToServer(imsQueryURL,theString,1007);
	} else {
		alert(msgList[80]);
	}
}

// write out find form
function writeSpecialFindRequest(findQuery,fieldList) {
	var theString = '<ARCXML version="1.1">\n<REQUEST>\n<GET_FEATURES outputmode="xml" geometry="false" envelope="true"';
	theString += ' featurelimit="' + maxFeaturesReturned + '" beginrecord="' + queryStartRecord + '">\n';
	theString += '<LAYER id="' + ActiveLayer + '" />\n';
	if (useLimitExtent) {
//alert('useLimitExtent set to true');
		// keep this within the limitExtent
		theString += '<SPATIALQUERY subfields="#ALL#" where="' + findQuery + '" >';
		theString += '<SPATIALFILTER relation="area_intersection">\n';
		theString += '<ENVELOPE maxx="' + forceComma(limitRight) + '" maxy="' + forceComma(limitTop) + '" minx="' + forceComma(limitLeft) + '" miny="' + forceComma(limitBottom) + '" />\n';
		theString += '</SPATIALFILTER>\n';
		theString += '</SPATIALQUERY>\n';
	} else {
//alert('useLimitExtent set to false');
//		theString += '<SPATIALQUERY subfields="#ALL#" where="' + findQuery + '" />\n';
//This works...but it returns all of the fields, even those we may not want to divulge.
//		theString += '<QUERY subfields="#ALL#" where="' + findQuery + '" />\n';
		theString += '<SPATIALQUERY subfields="#ALL#" where="' + findQuery + '" />\n';

//This works...and it returns only the key field...
//theString += '<QUERY subfields="SHAPE.fid #SHAPE# STATE01.GISPROD.ADATAXLOTS.PIN" where="' + findQuery + '" />\n';

	}
	theString += '</GET_FEATURES>\n';
	theString += '</REQUEST>\n';
	theString += '</ARCXML>';
	//alert(theString);
	selectLayer=ActiveLayer;
	selectType=ActiveLayerType;
	selectCount=0;
	hightlightedOne="";
	selectPoints.length=1;
	selectLeft.length=1;
	selectRight.length=1;
	selectTop.length=1;
	selectBottom.length=1;
//alert(theString);
	return theString;

}

function getLayerIndex(layerNm) {
	var jx = -1;
	for (var i=0;i<layerCount;i++) {
		if (LayerName[i] == layerNm) {
			jx = i;
		}
	}
	return jx;
}

function findParcelForm() {
	//determine the value the user wishes to find...
	var theValue = "R0367000070";
	if (useTextFrame) {
		parent.TextFrame.document.location= appDir + "findForm.htm";
	} else {
		Win1 = open(commonDir + "findFormSpecial.htm","QueryWindow","width=575,height=150,scrollbars=yes,resizable=yes");
	}
}




// find Form
function findForm() {
	if (checkIfActiveLayerAvailable()) {
		setLayerFields(ActiveLayerIndex);
		if (useTextFrame) {
			parent.TextFrame.document.location= appDir + "findForm.htm";
		} else {
//			Win1 = open(appDir + "findForm.htm","QueryWindow","width=575,height=150,scrollbars=yes,resizable=yes");
			Win1 = open(commonDir + "findForm.htm","QueryWindow","width=575,height=150,scrollbars=yes,resizable=yes");
		}
	}
}

// brb -- added for the FloodHazard application.
function zoomToParcel(theReply) {
	hideRetrieveData();
	lastQueryResponse = theReply;
	lastQueryLayer = parent.MapFrame.LayerName[ActiveLayerIndex];

	displayAttributeData(theReply);

	//We set the active layer
	ActiveLayerIndex = prevActiveLayerIndex;
	setLayerFields(ActiveLayerIndex);
}

//brb -- added to facilitate locating a person on the map by some method other than using the "Find" tool...which (apparently) takes too much effort for some uesrs.
//the cvtTypes are as follows:
//  DMS -- degrees, minutes, seconds (like 43, 15, 6.7, 114, 15, 20.0)
//  DM -- decimal degrees (like 43, 15.28, 114, 15.333)
//  DD -- decimal degrees (like 43.253, 114.253)
//  TRS, Address, IDTM83, County, Zipcode
//expect an envelope xmin, ymin, xmax, ymax
function sendLocateRequest(p1, p2, p3, p4) {
	if ((p3 == p1) && (p4 == p2)) {
		zoomToPoint(parseInt(p1), parseInt(p2), true, '');
	} else {
		zoomToEnvelope(p1, p2, p3, p4);
	}
}

//======================================================================================================================================
//brb -- added this...why is this not a standard feature of the HTML Viewer?  This routine calls zoomToEnvelope(p1, p2) after returning
// from the server.
// Params:  layer name (not ID), field to query (not alias, in all caps), the value to match...surround character values with aprostrophies 
// WARNING...THIS MAY NOT WORK PROPERLY WITH CHARACTER-STRING VALUES.
//======================================================================================================================================
function zoomToFeature(theLayerName, theQueryField, theValue) {
	selectCount=0;
	showBuffer=false;
	highlightedOne="";
	selectPoints.length=0;
	selectLeft.length=0;
	selectRight.length=0;
	selectTop.length=0;
	selectBottom.length=0;
	drawSelectBoundary=false;
	showGeocode=false;
	clickCount=0;
	totalMeasure=0;
	currentMeasure=0;
	selectionMode=1;
	var theNewQueryString = "";
	var theTempString = "";

	indx = getLayerIndex(theLayerName);

	//save the current active layer index and replace it with our "target" layer
	prevActiveLayerIndex = ActiveLayerIndex;
	ActiveLayerIndex = indx;
	setLayerFields(ActiveLayerIndex);
	var fieldListString = LayerIDField[indx] + " " + LayerShapeField[indx];
	theNewQueryString = "(" + theQueryField + " = " + theValue + ")";
	if (theNewQueryString!="") {
		showRetrieveData();
		showBuffer=false;
		theNewQueryString=makeXMLsafe(theNewQueryString);
		setQueryString = theNewQueryString;
		var theString = writeSpecialFindRequest(theNewQueryString,fieldListString);
		sendToServer(imsQueryURL,theString,1111);
	} else {
		alert(msgList[80]);
	}
}

// Process the reply from a ZoomToFeature request.
function processZTFReply(theReply) {
	var startpos;
	var lpos;
	var zpos;
	var endpos;
	var tmpX;
	var tmpY;

	lpos = theReply.indexOf("<FEATURES",1);
	if (lpos > -1) {
		zpos = theReply.indexOf("</FEATURES",lpos);

		startpos = theReply.indexOf("minx=",lpos);
		if ((startpos != -1) && (startpos<zpos)) {
		startpos += 6;
		endpos = theReply.indexOf(dQuote, startpos);
		tmpX = theReply.substring(startpos,endpos);
		tmpX = setDecimalString(tmpX);
		} else {
			tmpX = 0;
		}
		startpos = theReply.indexOf("miny=",endpos);
		if ((startpos != -1) && (startpos<zpos)) {
			startpos += 6;
			endpos = theReply.indexOf(dQuote, startpos);
			tmpY = theReply.substring(startpos,endpos);
			tmpY= setDecimalString(tmpY);
		} else {
			tmpY = 0;
		}
		zoomToPoint(parseInt(tmpX), parseInt(tmpY), true, '');
		hideRetrieveData();
	} else {
//		did not find it
	}
}
