/**
 * USGS_NATMAP_xml.js
 * functions for custom processing of xml requests and response
 * 
 */

nmXmlPresent = true;

// Variables that hold most recent response.
// Should be updated by any function that handles
// or processes a new map image request 
var respUrlChunk     = "";
var respTnmInfoChunk = "";

var enforceLimitExtent=true;

/**
 * refreshes the map images
 * works when either legend or layer frame displayed
 * 
 * replacement for sendMapXML() and TocFrame.updateLayers()
 */
function requestNewMainMap() {
	//showRetrieveMap();
	var modExt = checkEnvelopeRatio(reqExt.minX, reqExt.minY, reqExt.maxX, reqExt.maxY, iWidth, iHeight);
	if (enforceLimitExtent) {
		modExt = checkEnvelopeLimit(modExt[0] , modExt[1], modExt[2], modExt[3], limitMinX, limitMinY, limitMaxX, limitMaxY);
	}
	if (Math.abs(modExt[0]-modExt[2])< 0.0005 )
		alert(" Unable to zoom-in, requested operation exceeds zoom-in limits");
	else{
		reqExt.set(modExt[0],modExt[1],modExt[2],modExt[3]);
		var clientmode = "compact";
		if (useInstantRefresh) {
			clientmode = "expanded";
		}
		var commonArgs = generateCommonArgs();
	
		var theArgs = "request=map&ranking=" + rankingMode.name + "&clientmode=" + clientmode + "&" + commonArgs;
		sendRequest(theArgs, REQUEST_TYPE_GET_IMAGE);
		
		if (!useInstantRefresh) {
			var refreshBtnId=parent.RefreshFrame.document.getElementById("RefreshBtn");
			refreshBtnId.className='refresh inactive';
			refreshBtnId.value='Refresh Map';
		}
	}	
}

function customImageResponseProcess(theReply) {		
	// parse the response and assign values to responseUrlChunk 
	// and responseTnmInfoChunk vars
	extractResponseInfo(theReply);
	extractTnmInfo(respTnmInfoChunk);
	extractMapStackInfo(respUrlChunk);
	getXYs(respUrlChunk);
	if(tagX > curExt.minX && tagX < curExt.maxX && tagY > curExt.minY && tagY < curExt.maxY)
		tagIt(tagX,tagY);
	else	
		hideLayer("thePlaceLayer");

	if (legendVisible) {
		parent.TOCFrame.document.location = appDir + "Legend.htm";
	} else {
		parent.TOCFrame.document.location = appDir + "toc.htm";
		parent.TOCFrame.document.location.reload(true);
	}

	// override values returned from server immediately with user preferences.
	
	for (var i in WmsLayerId)
	{
		if (lp_LayerPreferred[WmsLayerId[i]] != null)
		{
			WmsLayerVisible[i] = lp_LayerPreferred[WmsLayerId[i]].preferred;
		}
	}
	
	populateDHTMLStack();

	updateScaleBar();
  
	if (toolMode == MAPTOOL_MEASURE) {
		updateMeasureBox();
	}
	
	if (hasOVMap) {
		if (requestOVMap) {
			document.ovImage.src = generateOVUrl();
			requestOVMap = false;
		} 
		if (ovIsVisible) {
			putExtentOnOVMap();
		} 
	} 

	//force reload of BottomFrame to get new partner links to show
	parent.BottomFrame.location.reload(true);

	if (mapInfoWinIsOpen) {
		MapInfoWin.location = appDir + "mapInfo.htm";
		MapInfoWin.location.reload(true);
	}

	//var sFactor = curExt.xSize / iWidth;
	///if (sFactor != mapScaleFactor) {
		//scale different from previous map so adjust scale ramp
		//getInscale();
		//mapScaleFactor = sFactor;
	//}
  setScaleToolBar (curExt, iHeight, iWidth);
}


// Phase D: extract IMAGE and TNMINFO chunks and 
// store in global vars
function extractResponseInfo(theReply) {

	// Get URLs	
	// get position of '</IMAGE>', extract contents of <IMAGE> tag
	var tmpImg = getInsideString(theReply, '<IMAGE ', '</IMAGE>', 0, 0, 'false');
	respUrlChunk = trim(tmpImg);
	respUrlChunk = formatXML(respUrlChunk);

	// extract contents of <TNMINFO> tag
	var tmpTnm = getInsideString(theReply, '<TNMINFO', '</TNMINFO>', 0, 0, 'false');
	tmpTnm = trim(tmpTnm);
	// find position of first '<TNMTHEME' open tag and trim off prefix 
	var i  = tmpTnm.indexOf('<TNMTHEME');
	respTnmInfoChunk = tmpTnm.substr(i);
	respTnmInfoChunk = formatXML(respTnmInfoChunk);
}

// Phase D: function to extract WMSLAYER info from TnmInfo chunk
// Parses TNMTHEME chunks of TNMINFO response to capture properties 
// of WMSLAYERs which are used for populating Layer and Legend panes,
// as well as metadata page.
function extractTnmInfo() {

	// parse the response for WMSLAYER legURL attributes
	// and store in a data structure
	var splitTnmClasses;
	var tnmThemeChunk;
	var tnmClassChunk;
	var wmsLayer;
	var wmsLayerIdx = 0;

	// reset arrays to zero-length: clear arrays
	WmsLayerId.length = 0;
	WmsLayerName.length = 0;
	WmsLayerTitle.length = 0;
	WmsLayerRecommended.length = 0;
	WmsLayerQueryable.length = 0;
	WmsLayerTransparent.length = 0;
	WmsLayerExtractable.length = 0;
	WmsLayerVisible.length = 0;
	WmsLayerZDepth.length = 0;
	WmsLayerLogoUrl.length = 0;
	WmsLayerMetadataUrl.length = 0;
	WmsLayerCapDocUrl.length = 0;
	WmsLayerServiceName.length = 0;
	WmsLayerDescription.length = 0;
	WmsLayerLegendUrl.length   = 0;
	WmsLayerPartnerName.length = 0;
	WmsLayerPartnerUrl.length = 0;
	WmsLayerClassId.length = 0;
	
	ClassLayerMap.length = 0;

	// retrieve the respTnmInfoChunk, split on '<TNMTHEME'
	var splitTnmThemes = respTnmInfoChunk.split('<TNMTHEME');

	// foreach TNMTHEME chunk, split on TNMCLASS
  for (var i = 1; i < splitTnmThemes.length; i++) {

		tnmThemeChunk = splitTnmThemes[i];

		splitTnmClasses = tnmThemeChunk.split('<TNMCLASS');

		// foreach TNMCLASS tag, extract wmsLayers
		for (var j = 1; j < splitTnmClasses.length; j++) {

			tnmClassChunk = splitTnmClasses[j];

			// grab class name
			var startpos = tnmClassChunk.indexOf('id=');
			var classId = getInsideString(tnmClassChunk, dQuote, dQuote, startpos, 0, false); 
			var classIndx = -1;
			for (var h = 0; h < ClassID.length; h++) {
				if (classId == ClassID[h]) {
					classIndx = h;
					break;
				}
			}

			splitWmsLayers = tnmClassChunk.split('<WMSLAYER');
		
			// start with idx of 1 - ignore first chunk
			for (var k = 1; k < splitWmsLayers.length; k++) {
				wmsLayer = splitWmsLayers[k];

				WmsLayerId[wmsLayerIdx] = getXmlAttribute(wmsLayer, "id");
				WmsLayerName[wmsLayerIdx] = getXmlAttribute(wmsLayer, "layerName");
				WmsLayerTitle[wmsLayerIdx] = getXmlAttribute(wmsLayer, "layerTitle");
				WmsLayerRecommended[wmsLayerIdx] = (getXmlAttribute(wmsLayer, "recommended") == "true");
				WmsLayerQueryable[wmsLayerIdx] = (getXmlAttribute(wmsLayer, "queryable") == "true");
				WmsLayerTransparent[wmsLayerIdx] = (getXmlAttribute(wmsLayer, "transparent") == "true");
				WmsLayerExtractable[wmsLayerIdx] = (getXmlAttribute(wmsLayer, "extractable") == "true");
				WmsLayerVisible[wmsLayerIdx] = (getXmlAttribute(wmsLayer, "displayed") == "true");
				WmsLayerZDepth[wmsLayerIdx] = getXmlAttribute(wmsLayer, "zDepth");
				WmsLayerLogoUrl[wmsLayerIdx] = getXmlAttribute(wmsLayer, "logoURL");
				WmsLayerMetadataUrl[wmsLayerIdx] = getXmlAttribute(wmsLayer, "metadataURL");
				WmsLayerCapDocUrl[wmsLayerIdx] = getXmlAttribute(wmsLayer, "capabilitiesURL");
				WmsLayerServiceName[wmsLayerIdx] = getXmlAttribute(wmsLayer, "serviceName");
				WmsLayerDescription[wmsLayerIdx] = getXmlAttribute(wmsLayer, "description");
				WmsLayerLegendUrl[wmsLayerIdx] = getXmlAttribute(wmsLayer, "legendURL");
				WmsLayerPartnerName[wmsLayerIdx] = getXmlAttribute(wmsLayer, "partnerName");
				WmsLayerPartnerUrl[wmsLayerIdx] = getXmlAttribute(wmsLayer, "partnerWebURL");
				WmsLayerClassId[wmsLayerIdx] = classId;

				if (ClassLayerMap[classIndx] == null || ClassLayerMap[classIndx] == undefined) {
					ClassLayerMap[classIndx] = wmsLayerIdx + ""; 
				}
				else {
					ClassLayerMap[classIndx] =  ClassLayerMap[classIndx] +  '|' + wmsLayerIdx;
				}
				wmsLayerIdx++;
			} // end wms loop
		} // end class loop
	} // end theme loop

	// DEBUG: dump loaded arrays
	if (debugOn >= 5) {
		var tmpStr = "";
		for (var i = 0; i < WmsLayerTitle.length; i++) {
			tmpStr = tmpStr + i + ' : ' +WmsLayerId[i] + ' : ' 
				+ WmsLayerName[i] + ' : '
				+ WmsLayerTitle[i] + ' : '
				+ WmsLayerRecommended[i] + ' : '
				+ WmsLayerQueryable[i] + ' : '
				+ WmsLayerTransparent[i] + ' : '
				+ WmsLayerExtractable[i]   + ' : '
				+ WmsLayerVisible[i] + ' : '
				+ WmsLayerZDepth[i] + ' : '
				+ WmsLayerLogoUrl[i] + ' : '
				+ WmsLayerMetadataUrl[i] + ' : '
				+ WmsLayerCapDocUrl[i] + ' : '
				+ WmsLayerServiceName[i] + ' : '
				+ WmsLayerDescription[i] + ' : '
				+ WmsLayerLegendUrl[i] + ' : '
				+ WmsLayerPartnerName[i] + ' : '
				+ WmsLayerPartnerUrl[i] + ' : ' 
				+ WmsLayerClassId[i] + "\r\n";
		}
		
		clientLog("extractTnmInfo loaded arrays", tmpStr);
		tmpStr = "";
		for (var i = 0; i < ClassLayerMap.length; i++) {
			tmpStr = tmpStr + ClassName[i] + ' : ' + ClassLayerMap[i] + "\r\n";
		}
		clientLog("extractTnmInfo class to layer maps", tmpStr);
		
		tmpStr = "";
		for (var i = 0; i < ThemeClassMap.length; i++) {
			tmpStr = tmpStr + ThemeName[i] + ' : ' + ThemeClassMap[i] + "\r\n";
		}
		clientLog("extractTnmInfo theme to class maps", tmpStr);
	}
}

// populates the MapStack* arrays
// imageBlock is the string containing the IMAGE part of the response
function extractMapStackInfo(imageBlock) {
	//clear the MapStack* arrays
	MapStackUrl.length = 0;
	MapStackWmsLayerId.length = 0;
	MapStackVisible.length = 0;

	// if OUTPUT elements in response, parse to extract urls and show map layers
	if (imageBlock.indexOf("OUTPUT") > -1) {
		var splitStrings = imageBlock.split("OUTPUT");
		if (debugOn >= 5) {	
			var outStr = "==================";
			for (var m=1; m < splitStrings.length; m++) {
				outStr += splitStrings[m] + "==================";	
			}
			clientLog(outStr);
		}
	
		// retrieve MapStack* attributes
		var theOutputItem;
		var idx = 0;
		for ( var i=1; i < splitStrings.length; i++) {
			theOutputItem = splitStrings[i];
			MapStackUrl[idx] = getXmlAttribute(theOutputItem, "url");
			if (useNewImageCommunication) {
				MapStackWmsLayerId[idx] = getXmlAttribute(theOutputItem, "id");
				MapStackVisible[idx] = (getXmlAttribute(theOutputItem, "visible") == "true");
			} else {
				MapStackVisible[idx] = true;
				MapStackWmsLayerId[idx] = "foo";
			}
			idx++;
		}
		if (debugOn >= 5) {
			var outStr = "";
			for(var i=0; i < MapStackUrl.length; i++) {
				outStr += "\n" + i + MapStackUrl[i] + ":" +
					MapStackWmsLayerId[i] + ":" +
					MapStackVisible[i];
			}
			clientLog("MapStack* loaded arrays", outStr);
		}
	}
}

function populateDHTMLStack(flushPrevious) {
	var doFlush = true;
	if (flushPrevious != null) {
		doFlush = flushPrevious;
	}
	if (debugOn >=5) {
		clientLogMemo("Start Rebuilding DHTMLStack");
	}

	populateDisplayStack();
	
	if (doFlush) {
		var blankImg = appDir + 'images/pixel.gif';
		// set all the previous images in the images stack to blank and hide them
		for (var i = 0; i < DisplayStackPrevSrc.length && i < maxOgcMapLayers; i ++) {
			document[DisplayStackImgName[i]]['src'] = blankImg;
 			hideLayer(DisplayStackLayerName[i]);
			DisplayStackPrevSrc[i] = blankImg;
			DisplayStackPrevVisible[i] = false;
		}
	}

	if (DisplayStackCurrSrc.length > maxOgcMapLayers) {
		var dropped = DisplayStackCurrSrc.length - maxOgcMapLayers;
		var theMsg = 'Maximum number of displayable layers (' + maxOgcMapLayers + ') exceeded.\n' + dropped + 'layers will not be displayed';
		alert(theMsg);
	}
	// run through current DisplayStack* and set url for visible layers
	var i = 0;
	var j = 0;
	var theIdx;
	var loopForward = (DisplayStackCurrSrc.length <= DisplayStackPrevSrc.length);
	for (i = 0, j = DisplayStackCurrSrc.length - 1; i < DisplayStackCurrSrc.length && i < maxOgcMapLayers && j >= 0; i++, j--) {
		if (loopForward) {
			theIdx = i;
		} else {
			theIdx = j;
		}
		if (DisplayStackCurrVisible[theIdx]) {
			if (DisplayStackCurrSrc[theIdx] != DisplayStackPrevSrc[theIdx]) { 
				document[DisplayStackImgName[theIdx]]['src'] = DisplayStackCurrSrc[theIdx];
			}
			if (theIdx >= DisplayStackPrevVisible.length || !DisplayStackPrevVisible[theIdx]) {
				showLayer(DisplayStackLayerName[theIdx]);
			}
		} else if (theIdx >= DisplayStackPrevVisible.length || DisplayStackPrevVisible[theIdx]) {
			hideLayer(DisplayStackLayerName[theIdx]);
		}
	}
	for (; i < DisplayStackPrevSrc.length && i < maxOgcMapLayers; i++) {
		hideLayer(DisplayStackLayerName[i]);
	}

	if (debugOn >=5) {
		clientLogMemo("Done Rebuilding DHTMLStack");
	}
}

function updateOneLayerInDHTMLStack(layerIdx) {
	for (var i = 0; i < MapStackWmsLayerId.length; i++) {
		if (MapStackWmsLayerId[i] == WmsLayerId[layerIdx]) {
			MapStackVisible[i] = WmsLayerVisible[layerIdx];
			break;
		}
	}
	populateDHTMLStack(false);
}

function updateDHTMLStack() {
	for (var i = 0; i < MapStackWmsLayerId.length; i++) {
		for (var j = 0; j < WmsLayerId.length; j++) {
			if (MapStackWmsLayerId[i] == WmsLayerId[j]) {
				MapStackVisible[i] = WmsLayerVisible[j];		 
				break;
			}
		}
	}
	populateDHTMLStack(false);
}

function populateDisplayStack() {
	var includeInvisible = (MapStackUrl.length <= maxOgcMapLayers);
	// copy CurrSrc to PrevSrc 
	DisplayStackPrevSrc.length = DisplayStackCurrSrc.length;
	DisplayStackPrevVisible.length = DisplayStackCurrVisible.length;
	for (var i = 0; i < DisplayStackCurrSrc.length; i++) {
		DisplayStackPrevSrc[i] = DisplayStackCurrSrc[i];
		DisplayStackPrevVisible[i] = DisplayStackCurrVisible[i];
	}
	DisplayStackCurrSrc.length = 0;
	DisplayStackCurrVisible.length = 0;
	var dsIdx = 0;
	for (var i = 0; i < MapStackUrl.length; i++) {
		if (MapStackVisible[i]) {
			DisplayStackCurrSrc[dsIdx] = MapStackUrl[i];
			DisplayStackCurrVisible[dsIdx] = true;
			dsIdx++;
		} else if (includeInvisible) {
			DisplayStackCurrSrc[dsIdx] = appDir + 'images/pixel.gif';
			DisplayStackCurrVisible[dsIdx] = false;
			dsIdx++;
		}
	}
	if (debugOn >=5) {
		var msg = "DisplayStackCurrSrc: " + DisplayStackCurrSrc.length + " " + DisplayStackCurrSrc + "\r\n";
		msg += "DisplayStackCurrVisible: " + DisplayStackCurrVisible.length + " " + DisplayStackCurrVisible + "\r\n";
		msg += "DisplayStackPrevSrc: " + DisplayStackPrevSrc.length + " " +  DisplayStackPrevSrc+ "\r\n";
		msg += "includeInvisible = " + includeInvisible;
		clientLog("DisplayStack* Info", msg);
	}

}

function getInitContext() {
	var theRequestArgs = 'request=initcontext&mode=class' + '&' + generateElementSetArg();
	sendRequest(theRequestArgs, REQUEST_TYPE_SERVICE_INFO)
}

function sendRequest(theArgs, theType) {

	if (okToSend) {
		XMLMode = theType;
		if (XMLMode == REQUEST_TYPE_GET_IMAGE) {
			showRetrieveMap();
		} else if (XMLMode == REQUEST_TYPE_FEATURE_INFO || XMLMode == REQUEST_TYPE_SERVICE_INFO) {
			showRetrieveData();
		}
		if (debugOn > 2) {
			clientLogRequest(msgList[6] + connectorURL + msgList[7] + theArgs);
		}
		okToSend = false;
		parent.PostFrame.location = connectorURL + theArgs;
	} else {
		//alert(msgList[2]);
		userResp = confirm("Error:  A new user request was received before the response to the previous request completed.\n\n" +
					"Click Cancel to cancel all requests and reload the viewer to the initial start state.  " +
					"(Note: Use the Cancel option when it appears likely no response will be received. This may be indicated by repeated occurrences of this message.)\n\n" +
					"Click OK to ignore the new request and continue to wait for the response.");
		if (userResp == true){
			hideRetrieveMap();
			hideRetrieveData();
		}
		else{
			parent.location.href="Run.htm" + document.location.search;
		}	
	}
}

function generateCommonArgs() {
	// new request format;
	var visLayers = "";
	var hideLayers = "";
	var visClasses = "";
	var hideClasses = "";

	for (var i = 0; i < ClassID.length; i++) {
		if (ClassVisible[i]) {
		  visClasses += ClassID[i] + ',';
		} else {
			hideClasses += ClassID[i] + ',';
		}
	}
  if (canToggleLayers) {
	visLayers += lp_getLayerListForPref(true);
	hideLayers += lp_getLayerListForPref(false);
	
	for (var i = 0; i < AddVisibleLayers.length; i++) {
		visLayers += AddVisibleLayers[i] + ',';
	}
				
	for (var i = 0; i < AddHiddenLayers.length; i++) {
		hideLayers += AddHiddenLayers[i] + ',';
	}
	visLayers = trimTrailingComma(visLayers);
	hideLayers = trimTrailingComma(hideLayers);

	}
	// reset arrays
	AddHiddenLayers.length = 0;
	AddVisibleLayers.length = 0;

	visClasses = trimTrailingComma(visClasses);
	hideClasses = trimTrailingComma(hideClasses);

	// get bounding box. constrain to show at most 5 decimal places
	var ext = [reqExt.minX,reqExt.maxY,reqExt.maxX,reqExt.minY];
	for(i=0;i<ext.length;i++){
		ext[i] = truncate(ext[i],5);
	  ext[i] -=0;
	}

	
	var bbox = ext[0] + ',' + ext[3] + ',' +ext[2] + ',' +ext[1];

	
	var theCommonArgs = generateElementSetArg();
	if (canToggleLayers) {
		theCommonArgs += "&visLayers=" + visLayers + "&hideLayers=" + hideLayers + "&";
	}
	theCommonArgs += "&visClasses=" + visClasses + "&hideClasses=" + hideClasses + "&bbox=" + bbox +
		"&imageHeight=" + iHeight + "&imageWidth=" + iWidth;

	return theCommonArgs;
}

function generateElementSetArg() {
  return "elementSet=" + elementSetId;
}

function updateScaleBar() {
  //add the scale bar 
  if (drawScaleBar && hasLayer("theAcetateLayer")) {
    var tmpAcetateUrl = acetateOgcUrlStub;
    if (useMetric) {
      if (curExt.maxY-curExt.minY < .02)  
	      tmpAcetateUrl += ",sBmeters";
      else
	      tmpAcetateUrl += ",sBkmsTnm";
    } else {
       if (curExt.maxY-curExt.minY < .02)  
	      tmpAcetateUrl += ",sBfeet";
      else
	     tmpAcetateUrl += ",sB";
    }
    tmpAcetateUrl += '&BBOX=' + curExt.minX + ',' + curExt.minY + ',' + curExt.maxX + ',' + curExt.maxY;
    tmpAcetateUrl += '&WIDTH=' + iWidth + '&HEIGHT=' + iHeight;
    document.theAcetateImage.src = tmpAcetateUrl;
    showLayer("theAcetateLayer");
  }
}
