// aimsXML.js
/*
*  JavaScript template file for ArcIMS HTML Viewer
*       dependent on ArcIMSparam.js, aimsCommon.js, aimsMap.js,
*/

var aimsXMLPresent=true;
 
    // index of current active MapService - default is zero - multiples in MultiService sample
 var activeMapServiceIndex = 0;
    // array for determining if extent coordinates should have comma instead of point for decimals
 var forceCommaInRequest = new Array();
 forceCommaInRequest[activeMapServiceIndex] = false;
 var forceCommaInOV = false;

/*
***************************************************************************************

Functions for sending XML requests and XML reponses

***************************************************************************************
*/

// global variables
    // change these in aimsCustom.js to send XML response to custom function.
    // use numbers >= 1000
var selectXMLMode = 6;
var identifyXMLMode = 7;
var queryXMLMode = 8;
var findXMLMode = 14;
var hyperlinkXMLMode = 15;

// common dynamic variables
var XMLMode = 1;
var okToSend = true;
var vList1 = new Array();
var vList2 = new Array();

var xHalf = xDistance/2;
var yHalf = yDistance/2;

// ending position to start parse scan of XML string
var xmlEndPos = 0;

var theImageType = "PNG";

var drawOVExtentBox=false;

var pastStart=false;
if (hasOVMap != true) pastStart = true;

// send in XML request and get XML response - uses helper applet
function sendToServer(URLString,XMLRequest,theType) {  
  if (parent.PostFrame.document.forms[0]!=null) {
    if (okToSend) { 
      XMLMode = theType;
      if (XMLMode==1) showRetrieveMap();
      if (debugOn>2) alert("ServiceName: " + URLString + "\nXMLRequest:\n " + XMLRequest);
      okToSend = false;
      var theForm = parent.PostFrame.document.forms[0];
      theForm.action=URLString + "&Form=True&Encode=True";
      theForm.ArcXMLRequest.value=XMLRequest;
      theForm.HeaderFile.value = headerFilePath;
      theForm.FooterFile.value = footerFilePath;
      theForm.submit();                
    } else {
      alert("Response from previous request(s) not received.");
      hideRetrieveMap();
      hideRetrieveData();
    }
  } else {
    alert("Form for posting request not found. Unable to communicate with server.");
    hideRetrieveMap();
    hideRetrieveData();
  }  
}

// send custom XML request. . . set up custom response handler
function sendCustomToServer(XMLRequest, theFunction, theType) {
  var theForm = parent.PostFrame.document.forms[0];
  theForm.JavaScriptFunction.value = theFunction;
  sendToServer(imsQueryURL,XMLRequest,theType)
}

// send the created xml request to map server
function sendMapXML() {
  beforeMapRefresh();
  showRetrieveMap();        
  var theText = writeXML();
  sendToServer(imsURL,theText,1);
}

// process the response xml
function processXML(theReplyIn) {
  theReplyIn = replacePlus(theReplyIn);
  var theReply = unescape(theReplyIn);
  okToSend = true;
  var theError = getXMLErrorMessage(theReply);
  switch(XMLMode) {
    case 1:
      getXYs(theReply);
      var theURL = "";
      theURL = getURL(theReply);
      if (theURL != "") {
        document.theImage.src = theURL;                
        afterMapRefresh();
        if (toolMode==3) {
          moveLayer("theMap",hspc,vspc);
          clipLayer("theMap",0,0,iWidth,iHeight);
          window.setTimeout('showLayer("theMap");',1000);
          if (hasLayer("theMapClicks")) {
            moveLayer("theMapClicks",hspc,vspc);
            clipLayer("theMapClicks",0,0,iWidth,iHeight);                
          }
        }                
      } else {                
        if (debugOn>0) {
          alert("Unable to display Map image\nDebug On\n" + theReply);
        } else {
          alert("Unable to display MapService\nServer returned:" + theError);
        }
      }
      if (toolMode==20) {
        updateMeasureBox();
      }
      if (legendVisible) {
        showLegend();
      }
      if (!noOverlay) {
        if (aimsClickPresent) {
          if (clickCount>0) {
            theText = writeOverlayXML();
            showRetrieveMap();
            sendToServer(imsURL,theText,901);
          }
        }
      }

      if (hasOVMap) {
      // usually do a call to get OVMap, but we are using an image. 
      if (!pastStart) {
          getOVXYs(theReply);
          pastStart=true;               
      }
      if (ovIsVisible) putExtentOnOVMap();          
      hideRetrieveMap();
      } else {
        hideRetrieveMap();
      }      
      break;            

    case 3:
        //  just get full extent - service info
        if (getLimitExtent) {
            getXYs(theReply);
            fullLeft = left;
            fullRight = right;
            fullTop = top;
            fullBottom = bottom;
            fullOVLeft = left;
            fullOVRight = right;
            fullOVTop = top;
            fullOVBottom = bottom;
            limitLeft = left;
            limitRight = right;
            limitTop = top;
            limitBottom = bottom;
        } else {
            fullLeft = limitLeft;
            fullRight = limitRight;
            fullTop = limitTop;
            fullBottom = limitBottom;
            fullOVLeft = limitLeft;
            fullOVRight = limitRight;
            fullOVTop = limitTop;
            fullOVBottom = limitBottom;                
        }
        fullWidth = Math.abs(fullRight - fullLeft);
        fullHeight = Math.abs(fullTop - fullBottom);
        fullOVWidth = Math.abs(fullOVRight - fullOVLeft);
        fullOVHeight = Math.abs(fullOVTop - fullOVBottom);
        theString = '<?xml version="1.0" encoding="UTF-8"?><ARCXML VERSION="1.1">\n<REQUEST>\n<GET_SERVICE_INFO />\n';
        theString += '</REQUEST>\n</ARCXML>';
        // get list of geocoding layers
        if((aimsGeocodePresent) && ((useGeocode) || (useReverseGeocode))) {
            theString = '<?xml version="1.0" encoding="UTF-8"?><ARCXML VERSION="1.1">\n<REQUEST>\n<GET_SERVICE_INFO  renderer="false" />\n';
            theString += '</REQUEST>\n</ARCXML>';
            sendToServer(imsGeocodeURL,theString,25);
        } else {
            theString = '<?xml version="1.0" encoding="UTF-8"?><ARCXML VERSION="1.1">\n<REQUEST>\n<GET_SERVICE_INFO  renderer="false" extensions="true" />\n';
            theString += '</REQUEST>\n</ARCXML>';
            sendToServer(imsURL,theString,4);
            useGeocode=false;
            useReverseGeocode=false;
        }    
        break

    case 4:
        // get service info - extent, layers
        processStartExtent(theReply);
        break

    case 7:
        // get identify response
        if (identPass1) {        
          calcIdentTables('Roads_Search',theReply);
          identify(e,42); //42 = composite layer, hardcoded ... is the numeric sequence number (from 0) of layer
          identPass1=false;
        } else { 
          calcIdentTables('Composite_Admin',theReply);
        }  
        break;

    case 14: 
        // identify
        if (LayerName[ActiveLayerIndex].indexOf("RdsSrch") > -1) {
          calcIdentTables("Roads_Search",theReply);
        } else {              
          calcIdentTables(LayerName[ActiveLayerIndex],theReply);
        }
        break;           

    case 99:
        // just put up a map
        var theURL = "";
        legendVisible=legendTemp;
        theURL = getURL(theReply);
        if (theURL != "") {
            document.theImage.src = theURL;
            if (!noOverlay) {
                if (clickCount>0) {
                    theText = writeOverlayXML();
                    showRetrieveMap();
                    sendToServer(imsURL,theText,901);
                } else {
                    if (hasLayer("theMapClicks")) {
                        document.theClickImage.src = blankImage;
                    }
                }
            }
        }
        else {
            alert(theReply + "\nUnable to display Map image");
        }
        hideRetrieveMap();

        break

    case 101:
        // print - get Map image
        printMapURL = getURL(theReply);
        printLegURL = getLegendURL(theReply);
        getPrintLegend();           
        break

    case 999:
        // get a blank map to get modified limit extents according image proportions
        var tempLeft = left;
        var tempRight = right;
        var tempTop = top;
        var tempBottom = bottom;
        getXYs(theReply)
        imageLimitLeft=left;
        imageLimitRight=right;
        imageLimitTop=top
        imageLimitBottom=bottom;
        left = tempLeft;
        right = tempRight;
        top = tempTop;
        bottom = tempBottom;
        sendMapXML();            
        break

    default:
        alert(theReply + "\nUnable to execute response. XMLMode: "+XMLMode);
    }
}

// write out a blank map. . . to get image extents from limit extents
function writeBlankMapXML() {
    var theString = '<?xml version="1.0" encoding="UTF-8"?><ARCXML VERSION="1.1">\n<REQUEST>\n<GET_IMAGE>\n<PROPERTIES>\n<ENVELOPE minx="' + limitLeft + '" miny="' + limitBottom + '" maxx="' + limitRight + '" maxy="' + limitTop + '" />\n<ENVIRONMENT><SEPARATORS cs="," ts=","/></ENVIRONMENT>';
    theString += '<IMAGESIZE height="' + iHeight + '" width="' + iWidth + '" />\n';
    var visString = "";
    // tell the server which layers are to be visible
    if (aimsLayersPresent) {
        theString += '<LAYERLIST >\n';
        for (var i=0;i<layerCount;i++) {
            theString += '<LAYERDEF name="' + LayerName[i] + '" visible="false" />\n';
            
        }
        theString += '</LAYERLIST>\n';
    }
    theString += '</PROPERTIES>\n';
    theString += '</GET_IMAGE>\n</REQUEST>\n</ARCXML>';
    sendToServer(imsURL,theString,999);
}

// prepare the request in xml format for Main Map
function writeXML() {
    var theString = '<?xml version="1.0" encoding="UTF-8"?><ARCXML VERSION="1.1">\n<REQUEST>\n<GET_IMAGE>\n<PROPERTIES>\n<ENVELOPE minx="' + left + '" miny="' + bottom + '" maxx="' + right + '" maxy="' + top + '" />';
    theString += '<IMAGESIZE height="' + iHeight + '" width="' + iWidth + '" />\n';
    var visString = "";
    if (aimsLayersPresent) {
        // tell the server which layers are to be visible
        if (toggleVisible) {
            theString += '<LAYERLIST >\n';
            for (var i=0;i<layerCount;i++) {
                if (LayerVisible[i]==1) {
                    theString += '<LAYERDEF id="' + LayerID[i] + '" visible="true" ';
                    if (aimsClassRenderPresent) {
                        theString += addSpecialRenderToMap(i);
                    } else {
                        theString += '/>\n';
                    }                    
                }
                else {
                    theString += '<LAYERDEF id="' + LayerID[i] + '" visible="false" />\n';
                }                
            }
            theString += '</LAYERLIST>\n';
        }
    }
    
    // map background color
    if (mapBackColor!="") {
        theString += '<BACKGROUND color="' + mapBackColor + '" />\n\n';
    }
    if (aimsLegendPresent) {
        // create a legend image
        if (legendVisible) theString += addLegendToMap();
    }
    
    theString += '</PROPERTIES>\n';
    
    // select
    if (aimsSelectPresent) {
        theString += addSelectToMap();
    }   
    
  if (aimsClickPresent){
    // clickpoints 
      var coordsDelimiter = " ";
      var pairsDelimiter = ";";
    if (clickCount>0) {
      // draw click points and lines between them on map
      var clickColor = selectColor;
      if (clickType==1) clickColor = clickMarkerColor;
      theString += '<LAYER type="acetate" name="allTheClicks">\n';

      if (clickCount>1) {
        theString += '<OBJECT units="database">\n<LINE coords="' + forceComma(clickPointX[0]) + coordsDelimiter + forceComma(clickPointY[0]);
        for (var i=1;i<clickCount;i++) {
          theString += pairsDelimiter  + forceComma(clickPointX[i]) + coordsDelimiter + forceComma(clickPointY[i]); 
        }
        theString += '" >\n';
        theString += '<SIMPLELINESYMBOL type="solid" color="' + clickMarkerColor;
        theString += '" width="3" />\n</LINE>\n</OBJECT>\n'; 
        theString += '<OBJECT units="database">\n<LINE coords="' + forceComma(clickPointX[0]) + coordsDelimiter + forceComma(clickPointY[0]);
        for (var i=1;i<clickCount;i++) {
          theString += pairsDelimiter  + forceComma(clickPointX[i]) + coordsDelimiter + forceComma(clickPointY[i]); 
        }
        theString += '" >\n';
        theString += '<SIMPLELINESYMBOL type="solid" color="255,255,255" width="1" />\n</LINE>\n</OBJECT>\n'; 
      }
      for (var i=0;i<clickCount;i++) {
        theString += '<OBJECT units="database">\n<POINT coords="' + forceComma(clickPointX[i]) + coordsDelimiter + forceComma(clickPointY[i]) + '">\n';
        theString += '<SIMPLEMARKERSYMBOL  type="' + clickMarkerType + '"';
        theString += ' color="' + clickMarkerColor + '" width="' + clickMarkerSize + '" />\n</POINT>\n</OBJECT>\n';
      }
      theString += '</LAYER>\n';
    }
  }    
    
    if ((aimsClickPresent) && (noOverlay)) {
        // clickpoints 
        if (clickCount>0) { 
            // draw click points and lines between them on map
            var clickColor = selectColor;
            if (clickType==1) clickColor = clickMarkerColor;
            theString += '<LAYER type="ACETATE" name="allTheClicks">\n';
 
            if (clickCount>1) {        
                theString += '<OBJECT units="DATABASE">\n<LINE coords="' + clickPointX[0] + " " + clickPointY[0];
                for (var i=1;i<clickCount;i++) {
                    theString += ";"  + clickPointX[i] + " " + clickPointY[i]; 
                }
                theString += '" >\n';
                theString += '<SIMPLELINESYMBOL type="SOLID" color="' + clickMarkerColor;
                theString += '" width="3" />\n</LINE>\n</OBJECT>\n'; 
                theString += '<OBJECT units="DATABASE">\n<LINE coords="' + clickPointX[0] + " " + clickPointY[0];
                for (var i=1;i<clickCount;i++) {
                    theString += ";"  + clickPointX[i] + " " + clickPointY[i]; 
                }
                theString += '" >\n';
                theString += '<SIMPLELINESYMBOL type="SOLID" color="255,255,255" width="1" />\n</LINE>\n</OBJECT>\n'; 
            }
            for (var i=0;i<clickCount;i++) {
                theString += '<OBJECT units="DATABASE">\n<POINT coords="' + clickPointX[i] + ' ' + clickPointY[i] + '">\n';
                theString += '<SIMPLEMARKERSYMBOL  type="' + clickMarkerType + '"';
                theString += ' color="' + clickMarkerColor + '" width="' + clickMarkerSize + '" />\n</POINT>\n</OBJECT>\n';
            }
            theString += '</LAYER>\n'; 
        }
    }

    // Copyright Notice
        theString += '<LAYER type="ACETATE" name="theCopyright">\n';        
        
        theString += '<OBJECT units="PIXEL">\n';
        theString += '<POLYGON coords="1 1;253 1;253 33;1 33;1 1"><SIMPLEPOLYGONSYMBOL fillcolor="255,255,255" filltransparency="0.9" overlap="true" /></POLYGON>\n';
        theString += '</OBJECT>\n';
        
        theString += '<OBJECT units="PIXEL">\n<TEXT coords="5 18" label="Melway maps reproduced with permission.">\n';
        theString += '<TEXTMARKERSYMBOL fontstyle="Normal" fontsize="13" ';
        theString += 'font="Arial" fontcolor="0,0,0" antialiasing="True" ';
        theString += 'shadow="32,32,32" overlap="false" ';
        theString += '/>\n</TEXT>\n</OBJECT>\n';

        theString += '<OBJECT units="PIXEL">\n<TEXT coords="5 5" label="Copyright Ausway Publishing Pty Ltd">\n';
        theString += '<TEXTMARKERSYMBOL fontstyle="Normal" fontsize="13" ';
        theString += 'font="Arial" fontcolor="0,0,0" antialiasing="True" ';
        theString += 'shadow="32,32,32" overlap="false" ';
        theString += '/>\n</TEXT>\n</OBJECT>\n';
               
        theString += '</LAYER>\n';

    if (drawNorthArrow) {
        // draw a north arrow
        theString += '<LAYER type="ACETATE" name="theNorthArrow">\n';
        theString += '<OBJECT units="PIXEL">\n<NORTHARROW type="' + NorthArrowType + '" size="' + NorthArrowSize + '" coords="' + NorthArrowCoords + '" shadow="32,32,32" ';
        theString += 'angle="' + NorthArrowAngle + '" antialiasing="True" overlap="False" />\n</OBJECT>\n';
        theString += '</LAYER>\n';
    }

    if (drawScaleBar) {
        // draw a scale bar
        //ScaleBarPrecision = numDecimals;
        theString += '<LAYER type="ACETATE" name="theScaleBar">\n';
        theString += '<OBJECT units="PIXEL">\n';
        theString += '<SCALEBAR coords="' + parseInt(iWidth * 0.60) + ' 2" outline="' + ScaleBarBackColor + '" ';

        theString += 'font="' + ScaleBarFont + '" fontcolor="' + ScaleBarFontColor + '" fontstyle="' + ScaleBarStyle + '" barcolor="' + ScaleBarColor + '" ';
        theString += 'mapunits="' + MapUnits + '" ';
        theString += 'scaleunits="' + ScaleBarUnits + '" antialiasing="True" ';

        var sDistance = getScaleBarDistance();
        if (sDistance<1) theString += 'precision="' + ScaleBarPrecision + '" ';
        
        theString += 'distance="' + sDistance + '" ';
        theString += 'fontsize="' + ScaleBarSize + '" barwidth="' + ScaleBarWidth + '" overlap="False"  />\n</OBJECT>\n';
        theString += '</LAYER>\n';  
    }
    theString += '</GET_IMAGE>\n</REQUEST>\n</ARCXML>';
    return theString;
}

// get the map extents from xml reply
function getXYs(theString) {
  var tempStr = "";
  var smallStr = "";
  var startpos = 0;
  var endpos = 0;
  var theReply = theString
  var theXYs =  getEnvelopeXYs(theString, 0)
  left = theXYs[0];
  bottom = theXYs[1];
  right = theXYs[2];
  top = theXYs[3];
  xDistance = Math.abs(right-left);
  yDistance = Math.abs(top-bottom);
  xHalf = xDistance / 2;
  yHalf = yDistance / 2;
  panX = xDistance * panFactor;
  panY = yDistance * panFactor;
  var sFactor = xDistance / iWidth

  if (aimsLayersPresent) {
    mapScaleFactor = sFactor;
    if (aimsLayersPresent) {
      if (LayerListOpen) writeLayerListForm();
    }            
  }
}


// get the map extents from xml reply
function getOVXYs(theString) {
    var tempStr = "";
    var smallStr = "";
    var startpos = 0;
    var endpos = 0;
    var theXYs =  getEnvelopeXYs(theString, 0)
    fullOVLeft = theXYs[0];
    fullOVBottom = theXYs[1];
    fullOVRight = theXYs[2];
    fullOVTop = theXYs[3];
    fullOVWidth = Math.abs(fullOVRight - fullOVLeft);
    fullOVHeight = Math.abs(fullOVTop - fullOVBottom);
}

// get URL
function getURL(theReply) {
    var theURL = "";
    var startpos = 0;
    var endpos = 0;
    var pos = theReply.indexOf("OUTPUT");
    if (pos != -1) {
        theURL = getInsideString(theReply,'url="',dQuote,pos,0,false);
        if (theURL!="") {
                endpos = theURL.lastIndexOf("/");
                theImageURLPath = theURL.substring(0,(endpos+1));
                startpos = theURL.lastIndexOf(".");
                var theType = theURL.substring(startpos+1,theURL.length);
                if (theType.toUpperCase()=="GIF") {
                    theImageType = "GIF";
                } else {
                    theImageType = "PNG";
                }
                if (theType.toUpperCase()=="JPG") {
                    noOverlay = true;
                }
                startpos = theReply.indexOf("file=",pos);
                if (startpos != -1) {
                    startpos += 6;
                    endpos = theReply.indexOf(dQuote,startpos);
                    thePath = theReply.substring(startpos,endpos);
                    endpos = thePath.lastIndexOf("\\");
                    
                    theImagePath = thePath.substring(0,(endpos+1));
                    startpos = endpos + 1;
                    endpos = thePath.indexOf("_",startpos);
                    theServiceName = thePath.substring(startpos,endpos);
                }
        }
    }
    legendImage = getLegendURL(theReply);
    return theURL;
}

// getLegendURL
function getLegendURL(theReply) {
    var theURL = "";
    var startpos = 0;
    var endpos = 0;
    var pos = theReply.indexOf("LEGEND");
    if (pos != -1) {
        theURL = getInsideString(theReply,'url="',dQuote,pos,0,false);
    }
    return theURL;
}

// just make a map with URL and  extent
function justGetMap(theURL, extentLeft, extentTop, extentRight, extentBottom, getOVMap) {
    if (getOVMap) mode = 1;
    if (extentLeft!="") left = extentLeft;
    if (extentTop!="") top = extentTop
    if (extentRight!="") right = extentRight;
    if (extentBottom!="") bottom = extentBottom;
    var theText = writeXML();
    if (debugOn==2) alert("Sending:\n\n" + theText);    
    sendToServer(theURL,theText,mode);    
}

// get min and max x,y's from xml stream . . . return an array with values
function getEnvelopeXYs(theString, startpos) {
    var theEnvelope = new Array();
    theString = theString.toUpperCase();
    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);
        theEnvelope[0] = parseFloat(theString.substring(startpos,endpos)); 
        startpos = theString.indexOf("MINY=",pos);
        startpos += 6;
        endpos = theString.indexOf(dQuote,startpos);
        theEnvelope[1] = parseFloat(theString.substring(startpos,endpos)); 
        startpos = theString.indexOf("MAXX=",pos);
        startpos += 6;
        endpos = theString.indexOf(dQuote,startpos);
        theEnvelope[2] = parseFloat(theString.substring(startpos,endpos)); 
        startpos = theString.indexOf("MAXY=",pos);
        startpos += 6;
        endpos = theString.indexOf(dQuote,startpos);
        theEnvelope[3] = parseFloat(theString.substring(startpos,endpos)); 
        xmlEndPos = endpos;
    }
    return theEnvelope;
alert("theEnvelope: "+theEnvelope);    
}

// check if there is an error message in the response
function getXMLErrorMessage(theString) {
    var pos1 = 0;
    var pos2 = 0;
    var pos3 = 0;
    theError = "";
    pos3 = theString.indexOf("<ERROR");
    if (pos3!=-1) {
        pos1 = theString.indexOf(">",pos3);
        pos1 += 1;
        pos2 = theString.indexOf("</ERROR");
        theError = theString.substring(pos1,pos2)
    }
    return theError;
}

function forceComma(theNumber) {
  var comma = ",";
  var dot = ".";
  var charOut = comma;
  var charIn = dot;
  var numberString = new String(theNumber);
  if (forceCommaInRequest[activeMapServiceIndex]) {
    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;
}

