//Map.js

Map = function (newId)
{
  OBJECT_MANAGER.addControl(this,'map', newId);
  this.id        = newId;
  this.config = null;
  this.mapNumber = 0;
  this.clientVersion = null;
  this.serverVersion = null;

  //interface objects directly controlled by the map object
  this.mapImage       = null;
  this.mapLoadImage = null;
  this.vmapPresent = false;
  this.vmapImage     = null;
  this.mapLoadImage = null;
  this.legendImage = null;
  this.customLegendImage = null;  //will be a string if a custom legend image should be used.

  //Ancillary controls
  this.bookmarkControl = null;
  this.markupControl = null;
  this.layerControl = null;
  this.bufferControl = null;
  this.themeControl = null;
  this.selectionControl = null;
  this.coordConvControl = null;
  this.measureControl = null;
  this.savedQueryControl = null;
  this.zoomBar = null;
  this.scaleBar = null;

  this.extensionMapClickHandlers = new Array();  // JPW
  
  //session specific data
  this.sessionID = null;
  this.extent    = new Array;        //extent of main map
  this.vmapExtent    = new Array;    //extent of vicinity map
  this.bookmarks = new Array();      //contains bookmarks for current session
  this.bookmark_redrawmaps = true;    //???
  this.legendVisible = null;          //is the legend currently displayed?
  this.legendSync    = false;         //does the legend match the current map display?
  this.numWaitingRequests = 0;        //counter for load image
  this.printOptions = null;
  this.zoomFactor = 1.5;
  this.initialExtent = null;
  this.activeMapScheme = null;
  this.firstLoad = true;

this.setConfig = function(newConfig)
{
  this.config = newConfig;
  if (this.layerControl)
    this.layerControl.draw();
  this.selectionsExist = false;
  var selectionCount = 0;
  this.buffersExist = false;
  var bufferCount = 0;
  var bufferableThemes = new Array();
  for (var currentTheme in this.config.themes)
  {
    if (this.config.themes[currentTheme].selectOptions != null)
    {
      this.selectionsExist = true;
      selectionCount++;
    }
    if (this.config.themes[currentTheme].bufferOptions != null)
    {
      bufferableThemes[bufferableThemes.length] = currentTheme;
      this.buffersExist = true;
      bufferCount++;
    }
  }
  
  this.vmapPresent = (this.config["vmap"]["resourceId"] != '');
  //Check for existence of ancillary controls and initialize
  if (this.selectionControl)
    this.selectionControl.initialize();
  if (this.bufferControl)
    this.bufferControl.initialize(bufferableThemes);
  if (this.coordConvControl)
    this.coordConvControl.draw();
  if (this.measureControl)
    this.measureControl.initialize();
  if (this.savedQueryControl)
    this.savedQueryControl.initialize();
};

this.initialize = function(sessionID)
{
  var map0 = Array(this.config["resourceId"], this.config["previousStates"],this.mapImage.width(),this.mapImage.height(),false);
  if (this.vmapImage != null)
  {
    var map1 = Array(this.config["vmap"]["resourceId"],0,this.vmapImage.width(),this.vmapImage.height(),true,0,this.config["vmap"]["slaveType"],this.config["vmap"]["boundBoxPercentMin"],this.config["vmap"]["styleSheet"]);
    var map_args = Array(map0,map1);
  }
  else
  {
    var map_args = Array(map0);
  }
  if (this.scalebar != null)
    this.scalebar.initialize();
  this.setWaiting(true);
  makeASyncPostRequest(this, 'Initialize', XMLRPC_URL,'GIS.Session.initialize',sessionID,map_args);
};

this.setMapLoadImage = function(newImagePanel)
{
  this.mapLoadImage = newImagePanel;
};

this.setMapImage = function(newMapImage)
{
  this.mapImage = newMapImage;
};

this.setVmapLoadImage = function(newImagePanel)
{
  this.vmapLoadImage = newImagePanel;
};

this.setVmapImage = function(newMapImage)
{
  this.vmapImage = newMapImage;
};

this.setLegendImage = function(newLegendImage, newLegendVisibility)
{
  this.legendImage = newLegendImage;
  this.legendVisible = newLegendVisibility;   //initial visibility of legend; will it be displayed when the page loads?
  this.legendSync    = false;
};

this.setWaiting = function(state)
{
  if (state)
  {
    if (this.mapImage != null)
      this.mapImage.setWaiting(true);
    if (this.vmapImage != null)
      this.vmapImage.setWaiting(true);
    this.numWaitingRequests++;
  }
  else
  {
    this.numWaitingRequests--;
    if (this.numWaitingRequests <= 0)
    {
      if (this.mapImage != null)
        this.mapImage.setWaiting(false);
      if (this.vmapImage != null)
        this.vmapImage.setWaiting(false);
    }
  }
};

this.getMapDimensions = function()
{
  if (this.vmapImage != null)
    return Array(Array(this.mapImage.width(),this.mapImage.height()),Array(this.vmapImage.imageNode.cbe.width(),this.vmapImage.imageNode.cbe.height()));    
  else
    return Array(Array(this.mapImage.width(),this.mapImage.height()))
};

this.loadLegend = function()
{
  if (this.customLegendImage!=null)
    this.legendImage.src = this.customLegendImage;
  else{
    if (_MAP_INITIALIZED){
      this.setWaiting(true);
      makeASyncPostRequest(this,'Legend',XMLRPC_URL,'GIS.Legend.getImage',this.sessionID,0,this.config["legendAttributes"]["width"],this.config["legendAttributes"]["height"],this.config["legendAttributes"]["color"],this.config["legendAttributes"]["font"],this.config["legendAttributes"]["fontSize"],this.config["legendAttributes"]["valueFontSize"],this.config["legendAttributes"]["cellSpacing"]);
    }
  }
};

this.loadLegendSync = function()
{
  if (this.customLegendImage!=null)
    this.legendImage.src = this.customLegendImage;
  else{
    var oldURL = this.legendImage.src; 
    this.setWaiting(true);
    var xmlrpcResponse = makeSyncPostRequest(XMLRPC_URL,'GIS.Legend.getImage',this.sessionID,0,this.config["legendAttributes"]["width"],this.config["legendAttributes"]["height"],this.config["legendAttributes"]["color"],this.config["legendAttributes"]["font"],this.config["legendAttributes"]["fontSize"],this.config["legendAttributes"]["valueFontSize"],this.config["legendAttributes"]["cellSpacing"]);
    var result = getXMLRPCResponseObject(xmlrpcResponse);
    var data = result.data;
    if(data != null)
    {
      this.legendImage.src = this.correctURL(data);
      //xMoveTo(this.legendImage,0,0);
      this.legendSync = true;
    }
    else
      alert('Communication Error:  Unable to load legend image');
    this.setWaiting(false);
  }
};

this.mouseMove = function(xPos,yPos,width,height,XPercent,YPercent,clickMode)
{
  switch (clickMode)
  {
    case 'MeasureDistance':
      this.setWaiting(false);
      var mapImageX = this.mapImage.left();
      var mapImageY = this.mapImage.top();
      var measurePointX = mapImageX + xPos;
      var measurePointY = mapImageY + yPos;
      var mapX = (XPercent * (this.extent[3]-this.extent[2])) + this.extent[2];  // XP * ExtentWidth + Left
      var mapY = (YPercent * (this.extent[1]-this.extent[0])) + this.extent[0];  // YP * ExtentHeight + Bottom
      if (this.measureControl != null)
      {
        this.measureControl.distanceCalculate({x:mapX,y:mapY});
        this.measureControl.areaCalculate({x:mapX,y:mapY});
      }
      else
        alert('Application Error\n'+this.id+'.click('+xPos+','+yPos+','+width+','+height+','+XPercent+','+YPercent+','+clickMode+')\nAttempting to process a measure point, but there is no measure control defined for the map object');
      break;
  }
};

this.click = function(xPos,yPos,width,height,XPercent,YPercent,clickMode)
{
  if (clickMode != 'ZoomBox')
    this.setWaiting(true);
  switch (clickMode)
  {
    case 'CoordConvSP2LatLon':  // ADDED-BY: JPW
      var config = OBJECT_MANAGER.getGuiValue('CoordConvConfig');
      var mapX = (XPercent * (this.extent[3]-this.extent[2])) + this.extent[2];  // XP * ExtentWidth + Left
      var mapY = (YPercent * (this.extent[1]-this.extent[0])) + this.extent[0];  // YP * ExtentHeight + Bottom
      var StatePlaneID = config.SP2LL_StatePlaneID;
      var DatumID = config.SP2LL_DatumID;
      makeASyncPostRequest(this,clickMode,XMLRPC_URL,'ArcIMS.CoordConvert.SP.to.LatLong',this.sessionID,0,mapX,mapY,StatePlaneID,DatumID);
      break;
    case 'MeasureDistance':  // ADDED-BY: JPW
      this.setWaiting(false);
      var mapImageX = this.mapImage.left();
      var mapImageY = this.mapImage.top();
      var measurePointX = mapImageX + xPos;
      var measurePointY = mapImageY + yPos;
      var mapX = (XPercent * (this.extent[3]-this.extent[2])) + this.extent[2];  // XP * ExtentWidth + Left
      var mapY = (YPercent * (this.extent[1]-this.extent[0])) + this.extent[0];  // YP * ExtentHeight + Bottom
      if (this.measureControl != null)
      {
        this.measureControl.distanceAddPoint(mapX,mapY);
        this.measureControl.distanceAddPointImage(measurePointX,measurePointY,xZIndex(this.mapImage.eventHandlerNode)+1);
        this.measureControl.distanceCalculate();
        this.measureControl.areaCalculate();
      }
      else
        alert('Application Error\n'+this.id+'.click('+xPos+','+yPos+','+width+','+height+','+XPercent+','+YPercent+','+clickMode+')\nAttempting to process a measure point, but there is no measure control defined for the map object');
      break;
    case 'dEmail':
      break;
    case 'ZoomIn':
      makeASyncPostRequest(this,clickMode,XMLRPC_URL,'GIS.Zoom.in.byPercent',this.sessionID,0,this.mapImage.width(),this.mapImage.height(),1.5,XPercent,YPercent);
      this.legendSync = false;
      break;
    case 'ZoomOut':
      makeASyncPostRequest(this,clickMode,XMLRPC_URL,'GIS.Zoom.out.byPercent',this.sessionID,0,this.mapImage.width(),this.mapImage.height(),1.5,XPercent,YPercent);
      this.legendSync = false;
      break;
    case 'Center':
      makeASyncPostRequest(this,clickMode,XMLRPC_URL,'GIS.Center.byPercent',this.sessionID,0,this.mapImage.width(),this.mapImage.height(),XPercent,YPercent);
      break;
    case 'Select':
      if (this.config.activeTheme != '')
      {
        if (this.config.themes[this.config.activeTheme].visibility && (this.config.themes[this.config.activeTheme].selectOptions != null)&&this.selectionsExist)   //only process if the theme is displayed and configured for selection
        {
          var activeThemeTolerance=-1;  // use the server-side default for this theme
          var activeThemeName = this.config.activeTheme;
          var GIS_stylesheet = this.config.themes[this.config.activeTheme].selectOptions.styleSheet;
          var fieldsList = this.config.themes[this.config.activeTheme].selectOptions.fieldList;
          var activeThemeMaxSelectCount = this.config.themes[this.config.activeTheme].selectOptions.limit;
          var requestDetails = new Object;
          requestDetails["request"] = 'newSelection';
          requestDetails["themeId"] = this.config.activeTheme;
          requestDetails["deselect"] = true;
          if(this.config.themes[this.config.activeTheme].selectOptions.sqlParams)
          {
            var configSQLParams = this.config.themes[this.config.activeTheme].selectOptions.sqlParams;
            var sqlParams = Array();
            for(var pos=0;pos < configSQLParams.length;pos++)
            {
              sqlParams[pos] = Array();
              sqlParams[pos][0] = configSQLParams[pos].pdqIdentifier;
              var fieldPairs = Array();
              var limits = Array();
              for(var lcv=0;lcv < configSQLParams[pos].fieldList.length;lcv++)
              {
                fieldPairs[lcv] = Array();
                fieldPairs[lcv][0] = configSQLParams[pos].fieldList[lcv].fieldName;
                fieldPairs[lcv][1] = configSQLParams[pos].fieldList[lcv].pdqFieldName;
              }
              sqlParams[pos][1] = fieldPairs;
              if (configSQLParams[pos].queryType != '')
              {
                limits[0] = configSQLParams[pos].queryType;
                limits[1] = configSQLParams[pos].numRows;
                limits[2] = configSQLParams[pos].startAt;
                sqlParams[pos][2] = limits;
              }
            }
            xypoints = Array(Array(XPercent,YPercent));
            coordsinpercent = true;
            makeASyncPostRequest(this.selectionControl,requestDetails,XMLRPC_URL,'GIS.Selection.entity.byPoint',this.sessionID,0,this.mapImage.width(),this.mapImage.height(),xypoints,coordsinpercent,activeThemeName,activeThemeTolerance,fieldsList,false,GIS_stylesheet,activeThemeMaxSelectCount,sqlParams);
          }
          else
          {
            xypoints = Array(Array(XPercent,YPercent));
            coordsinpercent = true;
            makeASyncPostRequest(this.selectionControl,requestDetails,XMLRPC_URL,'GIS.Selection.entity.byPoint',this.sessionID,0,this.mapImage.width(),this.mapImage.height(),xypoints,coordsinpercent,activeThemeName,activeThemeTolerance,fieldsList,false,GIS_stylesheet,activeThemeMaxSelectCount);
          }
          return;
        }
        else
        {
          this.setWaiting(false);
        }
      }
      else
        this.setWaiting(false);
      break;
    case 'BufferXY':
      var bufferDistance = this.bufferControl.getDistance();
      var bufferTheme = this.bufferControl.getActiveTheme();
      var bufferThemeParams = this.config.themes[bufferTheme].bufferOptions;
      var GIS_stylesheet = this.config.themes[bufferTheme].bufferOptions.styleSheet;
      var bufferFieldList = this.config.themes[bufferTheme].bufferOptions.fieldList;
      var clearFirst = true;
      var MaxBufferCount = this.config.themes[bufferTheme].bufferOptions.maxSelect;
      var bufferSQLparams = this.bufferControl.getSQLParams();
      if(this.config.themes[bufferTheme].bufferOptions.sqlParams != null)
      {
        var configSQLParams = this.config.themes[bufferTheme].bufferOptions.sqlParams;
        var sqlParams = Array();
        for(var pos=0;pos < configSQLParams.length;pos++)
        {
          sqlParams[pos] = Array();
          sqlParams[pos][0] = configSQLParams[pos].pdqIdentifier;
          var fieldPairs = Array();
          var limits = Array();
          for(var lcv=0;lcv < configSQLParams[pos].fieldList.length;lcv++)
          {
            fieldPairs[lcv] = Array();
            fieldPairs[lcv][0] = configSQLParams[pos].fieldList[lcv].fieldName;
            fieldPairs[lcv][1] = configSQLParams[pos].fieldList[lcv].pdqFieldName;
          }
          sqlParams[pos][1] = fieldPairs;
          if (configSQLParams[pos].queryType != '')
          {
            limits[0] = configSQLParams[pos].queryType;
            limits[1] = configSQLParams[pos].numRows;
            limits[2] = configSQLParams[pos].startAt;
            sqlParams[pos][2] = limits;
          }
        }
      }
      else
        var sqlParams = new Array();
      if (bufferSQLparams == null)
        makeASyncPostRequest(this.bufferControl,Array('BufferXY',bufferTheme),XMLRPC_URL,'GIS.Buffer.at.XY',this.sessionID,0,this.mapImage.width(),this.mapImage.height(),XPercent,YPercent,true,bufferTheme,bufferDistance,bufferFieldList,clearFirst,GIS_stylesheet,MaxBufferCount,sqlParams);
      else
        makeASyncPostRequest(this.bufferControl,Array('BufferXY',bufferTheme),XMLRPC_URL,'GIS.Buffer.at.XY',this.sessionID,0,this.mapImage.width(),this.mapImage.height(),XPercent,YPercent,true,bufferTheme,bufferDistance,bufferFieldList,clearFirst,GIS_stylesheet,MaxBufferCount,sqlparams,bufferSQLparams);
      break;
      default:  // JPW
        if (this.extensionMapClickHandlers[clickMode])
        {
          this.setWaiting(false);
          this.extensionMapClickHandlers[clickMode](xPos,yPos,width,height,XPercent,YPercent,clickMode);
        }
        break;
  }
  return;
};

this.selectByWindow = function (the_bottom,the_top,the_left,the_right)
{
  //perform a select by polygon operation using the percentages for the coordinates
  var xypoints = new Array();
  xypoints[0] = Array(the_left,the_bottom);
  xypoints[1] = Array(the_left,the_top);
  xypoints[2] = Array(the_right,the_top);
  xypoints[3] = Array(the_right,the_bottom);
  coordsinpercent = true;
  
  if (this.config.activeTheme != '')
  {
    if (this.config.themes[this.config.activeTheme].visibility && (this.config.themes[this.config.activeTheme].selectOptions != null)&&this.selectionsExist)   //only process if the theme is displayed and configured for selection
    {
      this.setWaiting(true);
      var activeThemeTolerance=-1;  // use the server-side default for this theme
      var activeThemeName = this.config.activeTheme;
      var GIS_stylesheet = this.config.themes[this.config.activeTheme].selectOptions.styleSheet;
      var fieldsList = this.config.themes[this.config.activeTheme].selectOptions.fieldList;
      var activeThemeMaxSelectCount = this.config.themes[this.config.activeTheme].selectOptions.limit;
      var requestDetails = new Object;
      requestDetails["request"] = 'newSelection';
      requestDetails["themeId"] = this.config.activeTheme;
      requestDetails["deselect"] = true;
      
      if(this.config.themes[this.config.activeTheme].selectOptions.sqlParams)
      {
        var configSQLParams = this.config.themes[this.config.activeTheme].selectOptions.sqlParams;
        var sqlParams = Array();
        for(var pos=0;pos < configSQLParams.length;pos++)
        {
          sqlParams[pos] = Array();
          sqlParams[pos][0] = configSQLParams[pos].pdqIdentifier;
          var fieldPairs = Array();
          var limits = Array();
          for(var lcv=0;lcv < configSQLParams[pos].fieldList.length;lcv++)
          {
            fieldPairs[lcv] = Array();
            fieldPairs[lcv][0] = configSQLParams[pos].fieldList[lcv].fieldName;
            fieldPairs[lcv][1] = configSQLParams[pos].fieldList[lcv].pdqFieldName;
          }
          sqlParams[pos][1] = fieldPairs;
          if (configSQLParams[pos].queryType != '')
          {
            limits[0] = configSQLParams[pos].queryType;
            limits[1] = configSQLParams[pos].numRows;
            limits[2] = configSQLParams[pos].startAt;
            sqlParams[pos][2] = limits;
          }
        }
        makeASyncPostRequest(this.selectionControl,requestDetails,XMLRPC_URL,'GIS.Selection.entity.byPolygon',this.sessionID,0,this.mapImage.width(),this.mapImage.height(),xypoints,coordsinpercent,activeThemeName,activeThemeTolerance,fieldsList,false,GIS_stylesheet,activeThemeMaxSelectCount,sqlParams);
      }
      else
      {
        makeASyncPostRequest(this.selectionControl,requestDetails,XMLRPC_URL,'GIS.Selection.entity.byPolygon',this.sessionID,0,this.mapImage.width(),this.mapImage.height(),xypoints,coordsinpercent,activeThemeName,activeThemeTolerance,fieldsList,false,GIS_stylesheet,activeThemeMaxSelectCount);
      }
      return;
    }
    else
    {
      this.setWaiting(false);
    }
  }
  else
    this.setWaiting(false);
};

this.bufferOnSelection = function(newSelectionHandle, newSourceTheme, newTargetTheme, newDistance, newSQLParams, newBufferSQLParams, newClearFirst)
{
  if (newSQLParams == null)
  {
    var bufferSQLparams = this.bufferControl.getSQLParams();
    if(this.config.themes[newTargetTheme].bufferOptions.sqlParams != null)
    {
      var configSQLParams = this.config.themes[newTargetTheme].bufferOptions.sqlParams;
      var sqlParams = Array();
      for(var pos=0;pos < configSQLParams.length;pos++)
      {
        sqlParams[pos] = Array();
        sqlParams[pos][0] = configSQLParams[pos].pdqIdentifier;
        var fieldPairs = Array();
        var limits = Array();
        for(var lcv=0;lcv < configSQLParams[pos].fieldList.length;lcv++)
        {
          fieldPairs[lcv] = Array();
          fieldPairs[lcv][0] = configSQLParams[pos].fieldList[lcv].fieldName;
          fieldPairs[lcv][1] = configSQLParams[pos].fieldList[lcv].pdqFieldName;
        }
        sqlParams[pos][1] = fieldPairs;
        if (configSQLParams[pos].queryType != '')
        {
          limits[0] = configSQLParams[pos].queryType;
          limits[1] = configSQLParams[pos].numRows;
          limits[2] = configSQLParams[pos].startAt;
         sqlParams[pos][2] = limits;
        }
      }
    }
    else
      var sqlParams = new Array();    
  }
  
  var bufferThemeParams = this.config.themes[newTargetTheme].bufferOptions;
  var GIS_stylesheet = this.config.themes[newTargetTheme].bufferOptions.styleSheet;
  var bufferFieldList = this.config.themes[newTargetTheme].bufferOptions.fieldList;
  var MaxBufferCount = this.config.themes[newTargetTheme].bufferOptions.maxSelect;
  var MapWidth = this.mapImage.width();
  var MapHeight = this.mapImage.height();

  this.setWaiting(true);
  if (bufferSQLparams == null)
    makeASyncPostRequest(this.bufferControl,Array('BufferOnSelection',newTargetTheme),XMLRPC_URL,'GIS.Buffer.on.Selection',this.sessionID,0,MapWidth,MapHeight,newSelectionHandle,newSourceTheme,newTargetTheme,newDistance,bufferFieldList,newClearFirst,GIS_stylesheet,MaxBufferCount,sqlParams);
  else
    makeASyncPostRequest(this.bufferControl,Array('BufferOnSelection',newTargetTheme),XMLRPC_URL,'GIS.Buffer.on.Selection',this.sessionID,0,MapWidth,MapHeight,newSelectionHandle,newSourceTheme,newTargetTheme,newDistance,bufferFieldList,newClearFirst,GIS_stylesheet,MaxBufferCount,sqlParams,newBufferSQLParams);
};

this.centerOnPoint = function(newMapX,newMapY)
{
  //accepts a new x,y coordinate pair in the current map units
  this.setWaiting(true);
  makeASyncPostRequest(this,'CenterOnPoint',XMLRPC_URL,'GIS.Center.onPoint',this.sessionID,0,this.mapImage.width(),this.mapImage.height(),newMapX,newMapY);
};

this.clickVmap = function (xPosition,yPosition,imageWidth, imageHeight)  // ASYNC
{
  var XPercent = xPosition / imageWidth;
  var YPercent = 1.0 - (yPosition / imageHeight);
  var mapX = (XPercent * (this.vmapExtent[3]-this.vmapExtent[2])) + this.vmapExtent[2];  // XP * ExtentWidth + Left
  var mapY = (YPercent * (this.vmapExtent[1]-this.vmapExtent[0])) + this.vmapExtent[0];  // YP * ExtentHeight + Bottom
  this.setWaiting(true);
  makeASyncPostRequest(this,'CenterOnPoint',XMLRPC_URL,'GIS.Center.onPoint',this.sessionID,0,this.mapImage.width(),this.mapImage.height(),mapX,mapY);
};

this.pan = function(DirStr)
{
  this.setWaiting(true);
  var mapData = makeASyncPostRequest(this,'Pan',XMLRPC_URL,'GIS.Pan.byDirection',this.sessionID,0,this.mapImage.width(),this.mapImage.height(),DirStr,0.4);
};

this.zoomInitialExtent = function()
{
  this.setWaiting(true);
  this.legendSync = false;
  makeASyncPostRequest(this,'ZoomInitialExtent',XMLRPC_URL,'GIS.Zoom.to.initialExtent',this.sessionID,0,this.mapImage.width(),this.mapImage.height());
};

this.zoomFullExtent = function()
{
  this.setWaiting(true);
  this.legendSync = false;
  makeASyncPostRequest(this,'ZoomInitialExtent',XMLRPC_URL,'GIS.Zoom.to.fullExtent',this.sessionID,0,this.mapImage.width(),this.mapImage.height());
};

this.zoomPresetExtent = function(newPresetName)
{
  this.setWaiting(true);
  this.legendSync = false;
  makeASyncPostRequest(this,'ZoomPresetExtent',XMLRPC_URL,'GIS.Zoom.to.presetExtent',this.sessionID,0,this.mapImage.width(),this.mapImage.height(),newPresetName);
};

this.zoomIn = function()
{
  this.setWaiting(true);
  this.legendSync = false;
  makeASyncPostRequest(this,'ZoomIn',XMLRPC_URL,'GIS.Zoom.in',this.sessionID,0,this.mapImage.width(),this.mapImage.height(),this.zoomFactor);
};

this.zoomOut = function()
{
  this.setWaiting(true);
  this.legendSync = false;
  makeASyncPostRequest(this,'ZoomOut',XMLRPC_URL,'GIS.Zoom.out',this.sessionID,0,this.mapImage.width(),this.mapImage.height(),this.zoomFactor);
};

this.zoomTo = function(themeIndex, SQLstr, select)
{
  //Zooms to an entity on a theme, with the option to select the object.
  //themeIndex is the index of the theme to perform the zoom on
  //SQLstr is a query string used to identify the unique object
  //select is a boolean indicating whether or not to select the object if it is found
  //
  this.setWaiting(true);
  this.legendSync = false;
  if (!this.selectionsExist)
    select = false;
  var GIS_stylesheet = this.config.themes[themeIndex].selectOptions.styleSheet;
  if (select)
  {
    var requestDetails = new Object;
    requestDetails["request"] = 'newSelection';
    requestDetails["themeId"] = themeIndex;
    requestDetails["deselect"] = false;
    if(this.config.themes[themeIndex].selectOptions.sqlParams != null)
    {
      var configSQLParams = this.config.themes[themeIndex].selectOptions.sqlParams;
      var sqlParams = Array();
      for(var pos=0;pos < configSQLParams.length;pos++)
      {
        sqlParams[pos] = Array();
        sqlParams[pos][0] = configSQLParams[pos].pdqIdentifier;
        var fieldPairs = Array();
        var limits = Array();
        for(var lcv=0;lcv < configSQLParams[pos].fieldList.length;lcv++)
        {
          fieldPairs[lcv] = Array();
          fieldPairs[lcv][0] = configSQLParams[pos].fieldList[lcv].fieldName;
          fieldPairs[lcv][1] = configSQLParams[pos].fieldList[lcv].pdqFieldName;
        }
        sqlParams[pos][1] = fieldPairs;
        if (configSQLParams[pos].queryType != '')
        {
          limits[0] = configSQLParams[pos].queryType;
          limits[1] = configSQLParams[pos].numRows;
          limits[2] = configSQLParams[pos].startAt;
          sqlParams[pos][2] = limits;
        }
      }
      makeASyncPostRequest(this.selectionControl,requestDetails,XMLRPC_URL,'GIS.Zoom.to.entities',this.sessionID,0,this.mapImage.width(),this.mapImage.height(),themeIndex,this.config.themes[themeIndex].selectOptions.fieldList,SQLstr,this.config.themes[themeIndex].selectOptions.zoomExtentRatio,1,select,select,false,GIS_stylesheet,sqlParams);
    }
    else
      makeASyncPostRequest(this.selectionControl,requestDetails,XMLRPC_URL,'GIS.Zoom.to.entities',this.sessionID,0,this.mapImage.width(),this.mapImage.height(),themeIndex,this.config.themes[themeIndex].selectOptions.fieldList,SQLstr,this.config.themes[themeIndex].selectOptions.zoomExtentRatio,1,select,select,false,GIS_stylesheet);
  }
  else
  {
    makeASyncPostRequest(this,'zoomTo',XMLRPC_URL,'GIS.Zoom.to.entities',this.sessionID,0,this.mapImage.width(),this.mapImage.height(),themeIndex,this.config.themes[themeIndex].selectOptions.fieldList,SQLstr,this.config.themes[themeIndex].selectOptions.zoomExtentRatio,1,select,select,false,GIS_stylesheet);
  }
};

this.zoomToSelection = function(themeIndex, SQLstr, select)
{
  this.setWaiting(true);
  this.legendSync = false;
  var GIS_stylesheet = this.config.themes[themeIndex].selectOptions.styleSheet;
  if (select)
  {
    if(this.config.themes[themeIndex].selectOptions.sqlParams != null)
    {
      var configSQLParams = this.config.themes[themeIndex].selectOptions.sqlParams;
      var sqlParams = Array();
      for(var pos=0;pos < configSQLParams.length;pos++)
      {
        sqlParams[pos] = Array();
        sqlParams[pos][0] = configSQLParams[pos].pdqIdentifier;
        var fieldPairs = Array();
        var limits = Array();
        for(var lcv=0;lcv < configSQLParams[pos].fieldList.length;lcv++)
        {
          fieldPairs[lcv] = Array();
          fieldPairs[lcv][0] = configSQLParams[pos].fieldList[lcv].fieldName;
          fieldPairs[lcv][1] = configSQLParams[pos].fieldList[lcv].pdqFieldName;
        }
        sqlParams[pos][1] = fieldPairs;
        if (configSQLParams[pos].queryType != '')
        {
          limits[0] = configSQLParams[pos].queryType;
          limits[1] = configSQLParams[pos].numRows;
          limits[2] = configSQLParams[pos].startAt;
          sqlParams[pos][2] = limits;
        }
      }
      makeASyncPostRequest(this,'zoomToSelection',XMLRPC_URL,'GIS.Zoom.to.entities',this.sessionID,0,this.mapImage.width(),this.mapImage.height(),themeIndex,"*",SQLstr,this.config.themes[themeIndex].selectOptions.zoomExtentRatio,1,select,select,false,GIS_stylesheet,sqlParams);
    }
    else
      makeASyncPostRequest(this,'zoomToSelection',XMLRPC_URL,'GIS.Zoom.to.entities',this.sessionID,0,this.mapImage.width(),this.mapImage.height(),themeIndex,"*",SQLstr,this.config.themes[themeIndex].selectOptions.zoomExtentRatio,1,select,select,false,GIS_stylesheet);
  }
  else
    makeASyncPostRequest(this,'zoomToSelection',XMLRPC_URL,'GIS.Zoom.to.entities',this.sessionID,0,this.mapImage.width(),this.mapImage.height(),themeIndex,"*",SQLstr,this.config.themes[themeIndex].selectOptions.zoomExtentRatio,1,select,select,false,GIS_stylesheet);
};

this.zoomToExtent = function(newExtent)
{
  this.setWaiting(true);
  this.legendSync = false;
  makeASyncPostRequest(this,'ZoomToExtent',XMLRPC_URL,'GIS.Zoom.to.extent',this.sessionID,0,this.mapImage.width(),this.mapImage.height(),newExtent);
};

this.refresh = function()
{
  this.setWaiting(true);
  makeASyncPostRequest(this,'MapRedraw',XMLRPC_URL,'GIS.Map.redraw',this.sessionID,0,this.mapImage.width(),this.mapImage.height());
};

this.redraw = function()
{
  this.setWaiting(true);
  makeASyncPostRequest(this,'MapRedraw',XMLRPC_URL,'GIS.Map.redraw',this.sessionID,0,this.mapImage.width(),this.mapImage.height());
};

this.zoomToPrevious = function()
{
  this.setWaiting(true);
  this.legendSync = false;
  makeASyncPostRequest(this,'ZoomPrevious',XMLRPC_URL,'GIS.Zoom.to.previousExtent',this.sessionID,0,this.mapImage.width(),this.mapImage.height());
};

this.zoomToWindow = function(bottom,top,left,right)
{
  this.setWaiting(true);
  this.legendSync = false;
  makeASyncPostRequest(this,'ZoomWindow',XMLRPC_URL,'GIS.Zoom.to.windowPercent',this.sessionID,0,this.mapImage.width(),this.mapImage.height(),bottom,top,left,right);
};

this.zoombar = function (ratio,divnum,numdivs)
{
  this.setWaiting(true);
  this.legendSync = false;
  makeASyncPostRequest(this,'ZoomBar',XMLRPC_URL,'GIS.Zoom.by.bar',this.sessionID,0,this.mapImage.width(),this.mapImage.height(),ratio,divnum,numdivs);
};

this.setThemes = function(newThemeList)
{
  for (i=0; i<newThemeList.length; i++)
  {
    this.themeLookup[newThemeList[i][0]] = i;
    this.themes[i] = new Array(newThemeList[i], "off");
  }
};

this.getThemeByName = function(newThemeName)
{
  return this.themes[this.themeLookup[newThemeName]];
};

this.setActiveTheme = function(newActiveTheme)
{
  this.config.activeTheme = newActiveTheme;
  if (this.layerControl)
    this.layerControl.update();
};

this.getBookmarkList = function ()
{
  //does not set the load image since it does not interfere with map operations
  if (this.bookmarkControl!=null)
    makeASyncPostRequest(this,'getBookmarkList',XMLRPC_URL,'GIS.Geobookmark.get.list',this.sessionID);
};

this.addBookmark = function (name)
{
  if (name != '')
    makeASyncPostRequest(this,'addBookmark',XMLRPC_URL,'GIS.Geobookmark.add.state',this.sessionID,0,name,false,false);
};

this.gotoBookmark = function (bookmarkIndex)
{
  var name = this.bookmarks[bookmarkIndex];  
  this.setWaiting(true);
  this.legendSync = false;
  makeASyncPostRequest(this,'gotoBookmark',XMLRPC_URL,'GIS.Geobookmark.restore.state',this.sessionID,0,name,this.bookmark_redrawmaps,true,true,true,false);
};

this.removeBookmark = function(bookmarkIndex)
{
  var name = this.bookmarks[bookmarkIndex];  
  this.setWaiting(true);
  makeASyncPostRequest(this,'removeBookmark',XMLRPC_URL,'GIS.Geobookmark.remove.state',this.sessionID,name);
};

this.loadThemes = function()
{
  this.setWaiting(true);
  makeASyncPostRequest(this,'getThemes',XMLRPC_URL,'GIS.Themes.getList',this.sessionID,0);
};

this.setThemeState = function(themeName, visible)
{
  var themeArray = new Array();      //array of theme information to pass to server
  themeArray[0] = new Array();       //an individual theme
  themeArray[0][0] = themeName;       //fetch theme name
  themeArray[0][1] = visible;         //new state
  this.config["themes"][themeName]["visibility"] = visible;
  this.legendSync = false;
  makeASyncPostRequest(this, 'setThemes', XMLRPC_URL, 'GIS.Themes.setList', this.sessionID, 0, themeArray);
};

this.clearSelection = function(themeIndex, selectionHandle)
{
  var requestDetails = new Object;
  requestDetails.request = 'clearSelection';
  requestDetails.themeIndex = themeIndex;
  requestDetails.handle = selectionHandle;

  this.setWaiting(true);
  var mapData = makeASyncPostRequest(this.selectionControl,requestDetails,XMLRPC_URL,'GIS.Selection.clear.EntityFromTheme',this.sessionID,0,themeIndex, selectionHandle, this.mapImage.width(),this.mapImage.height());
};

this.clearDuplicateSelection = function(themeIndex, selectionHandle)
{
  var requestDetails = new Object;
  requestDetails.request = 'clearDuplicateSelection';
  requestDetails.themeIndex = themeIndex;
  requestDetails.handle = selectionHandle;

  this.setWaiting(true);
  var mapData = makeASyncPostRequest(this.selectionControl,requestDetails,XMLRPC_URL,'GIS.Selection.clear.EntityFromTheme',this.sessionID,0,themeIndex, selectionHandle, this.mapImage.width(),this.mapImage.height());
};

this.clearThemeSelections = function(themeIndex)
{
  var requestDetails = new Object;
  requestDetails.request = 'clearTheme';
  requestDetails.themeIndex = themeIndex;

  this.setWaiting(true);
  var mapData = makeASyncPostRequest(this.selectionControl,requestDetails,XMLRPC_URL,'GIS.Selection.clear.AllFromTheme',this.sessionID,0,themeIndex);
};

this.clearSyncSelection = function(themeIndex, selectionHandle)
{
  this.setWaiting(true);
  var xmlrpcResponse = makeSyncPostRequest(XMLRPC_URL,'GIS.Selection.clear.EntityFromTheme',this.sessionID,0,this.themes[themeIndex][0][0], selectionHandle, this.mapImage.width(),this.mapImage.height());
  var mapData = getXMLRPCResponseObject(xmlrpcResponse);
  this.setWaiting(false);
};

this.clearThemeBuffer = function(themeName,bufferHandle)
{
  this.setWaiting(true);
  makeASyncPostRequest(this.bufferControl,Array('clearThemeBuffer',themeName,bufferHandle),XMLRPC_URL,'GIS.Buffer.clear.FromTheme',this.sessionID,0,themeName, bufferHandle, this.mapImage.width(),this.mapImage.height());
};

this.callback = function(serverReplyDoc, pendingOperation)
{
  var clearMeasurePoints = false;
  var result = getXMLRPCResponseObject(serverReplyDoc);
  if (result.XMLRPC_FAULT){
    switch(parseInt(result.XMLRPC_FAULT_CODE))
    {
      case 1018: // No Buffer elements found
        break;
      default:
        alert('An error occurred in a Map request.\n\nOperation:  '+pendingOperation+'\nError Code: '+result.XMLRPC_FAULT_CODE+'\nError Message:\n'+result.XMLRPC_FAULT_MESSAGE);
    }
    this.setWaiting(false);
  }
  else{
    var data = result.data;
    if (data==null){
      alert('An Error occurred in a Map request.\n\nOperation:  '+pendingOperation+'\nFault Code: -1\nError Message:\nAn invalid response was returned from the server.');
      this.setWaiting(false);
      this.refresh();
      return null;
    }
    switch (pendingOperation)
    {
      case 'CoordConvSP2LatLon':  // ADDED-BY: JPW
        if (this.coordConvControl)
          this.coordConvControl.callback(data,pendingOperation);
        break;
      case 'Initialize':
        _MAP_INITIALIZED = true;
        if (this.firstLoad)
        {
          this.firstLoad = false;
          this.initialExtent = cloneObject(data[0][1]);
        }
        this.extent = data[0][1];
        if (this.mapImage != null)
        {
          this.setWaiting(true);
          this.mapImage.imageNode.mapObject = this;
          this.mapImage.imageNode.onload=this.imageLoadCallback;
          this.mapImage.imageNode.src = this.correctURL(data[0][0]);
        }
        if (this.vmapImage != null)
        {
          this.setWaiting(true);
          this.vmapImage.imageNode.mapObject = this;
          this.vmapImage.imageNode.onload=this.imageLoadCallback;
          this.vmapImage.imageNode.src = this.correctURL(data[1][0]);
        }
        this.vmapExtent = data[1][1];
        this.sessionID = data[data.length-1];
        document.setSessionID(this.sessionID);
        this.extent = Array(data[0][1][0],data[0][1][1],data[0][1][2],data[0][1][3]); //btlr
        this.loadThemes();
        this.loadLegend();
        this.getBookmarkList();
        if (this.markupControl != null)
        {
          this.markupControl.initialize();
          this.markupControl.initUser();
        }
        if (this.directMappingControl)
        {
          this.directMappingControl.initUser();
        }
        if (this.selectionControl != null)
          this.selectionControl.initialize();
        if (document.savedQueryControl)
          document.savedQueryControl.initialize();
        if (this.zoomBar)
          this.zoomBar.initialize();
        runCMDs();
        break;
      case 'getThemes':
        for (i = 0; i < data.length; i++){
          try{
            this.config["themes"][data[i][0]]["visibility"] = data[i][1];
          }
          catch(e)
          {
            alert('Warning:\nUnable to set the visibility for map layer "'+data[i][0]+'"\nThere may be a mismatch between the client configuration and the map resource.');
          }
        }
        if (this.layerControl)
          this.layerControl.update();
        break;
      case 'setThemes':
        break;
      case 'Legend':
        if (this.legendImage != null)
          this.legendImage.src = this.correctURL(data);
        this.legendSync = true;
        break;
      case 'LoadLayers':
        break;
      case 'getBookmarkList':
        if (this.bookmarkControl!=null)
          this.bookmarkControl.callback(data,'getBookmarkList');
        break;
      case 'addBookmark':
        if (this.bookmarkControl!=null)
          this.bookmarkControl.callback(data,'addBookmark');
        this.getBookmarkList();
        break;
      case 'removeBookmark':
        if (this.bookmarkControl!=null)
          this.bookmarkControl.callback(data,'removeBookmark');
        this.getBookmarkList();
        break;
      case 'gotoBookmark':
        if (this.mapImage != null)
        {
          this.setWaiting(true);
          this.mapImage.imageNode.src = this.correctURL(data[0][1]);
        }
        if (this.vmapImage != null)
        {
          this.setWaiting(true);
          this.vmapImage.imageNode.src = this.correctURL(data[1][1]);
        }
        this.extent = Array(data[0][2][0],data[0][2][1],data[0][2][2],data[0][2][3]); //btlr
        this.loadThemes();
        if (this.legendVisible)
          this.loadLegend();
        clearMeasurePoints = true;
        break;
      case 'Select':
        break;
      case 'dEmail':
        break;
      case 'BufferXY':
        this.extent = Array(data[0][0][2][0],data[0][0][2][1],data[0][0][2][2],data[0][0][2][3]); //btlr
        if (this.mapImage != null){
          this.setWaiting(true);
          this.mapImage.imageNode.src = this.correctURL(data[0][0][1]);
        }
        if (this.vmapImage != null){
          this.setWaiting(true);
          this.vmapImage.imageNode.src = this.correctURL(data[0][1][1]);
        }
        break;
      case 'zoomTo':
      case 'zoomToSelection':
        if (this.mapImage != null){
          this.setWaiting(true);
          this.mapImage.imageNode.src = this.correctURL(data[0][0][1]);
        }
        if (this.vmapImage != null){
          this.setWaiting(true);
          this.vmapImage.imageNode.src = this.correctURL(data[0][1][1]);
        }
        if (this.legendVisible)
          this.loadLegend;
        this.extent = Array(data[0][0][2][0],data[0][0][2][1],data[0][0][2][2],data[0][0][2][3]); //btlr
        clearMeasurePoints = true;
        break;
      case 'getExportedMap':
        this.downloadExportedMap(data);
        break;
      case 'printMap':
        document.printMap(result.data);
        break;
      default:
        this.extent = Array(data[0][2][0],data[0][2][1],data[0][2][2],data[0][2][3]); //btlr
        if (this.mapImage != null){
          this.mapImage.imageNode.src = this.correctURL(data[0][1]);
          this.setWaiting(true);
        }
        if (this.vmapImage != null){
          this.setWaiting(true);
          this.vmapImage.imageNode.src = this.correctURL(data[1][1]);
        }
        if (this.legendVisible && !this.legendSync)
        {
          this.loadLegend();
        }
        clearMeasurePoints = true;
        break;
    }
  }
  if ((this.measureControl != null) && clearMeasurePoints)
  {
    this.measureControl.distanceReset();
  }
  if ((this.zoomBar!=null)&&(this.zoomBar.initialized))
    this.zoomBar.highlightNearestDiv();
  if (this.scalebar)
    this.scalebar.drawScalebar();
  this.setWaiting(false);
};

this.imageLoadCallback = function()
{
  this.mapObject.setWaiting(false);
};

this.selectionCallback = function (data)
{
  var returnValue;
  if (data)
  {
    this.mapImage.imageNode.src = this.correctURL(data[0][1]);
    if (this.vmapImage != null)
      this.vmapImage.imageNode.src = this.correctURL(data[1][1]);
    this.extent = Array(data[0][2][0],data[0][2][1],data[0][2][2],data[0][2][3]); //btlr
    returnValue = true;
  }
  else
    returnValue = null;
  this.setWaiting(false);
  if (data != null)
    if (this.onSelect)
      this.onSelect();
  return returnValue;
};

this.correctURL = function (newURL)
{
  var returnValue = newURL;
  if (typeof(returnValue) != 'string')
    alert(typeof(returnValue)+' :: '+returnValue);
  if (returnValue.substr(0,1) == '/')  //trying to deal with relative paths
  {
    returnValue = 'http://'+this.config["imsHostname"]+newURL;
  }
  else
  {
    var url = /(\w+):\/\/([^\/]+)\/(\S*)/;
    var result = newURL.match(url);
    if (result == null)
      returnValue = newURL;  // setup doesn't have an ip or fully qualified name separated w/ .'s
    else
      returnValue = result[1]+'://'+this.config["imsHostname"]+'/'+result[3];
  }
  return returnValue;
};

this.exportMap = function()
{
  this.setWaiting(true);
  makeASyncPostRequest(this,'getExportedMap',XMLRPC_URL,'ArcIMS.Map.export',this.sessionID,0,this.mapImage.width(),this.mapImage.height());
};

this.downloadExportedMap = function(url)
{
  url = this.correctURL(url);
  downloadFile(url);
};

this.print = function()
{
  //arguments[0] = array of name,value pairs for placeholder variables
  var placeholderVariables = new Array();
  if (this.config.printConfig.defaultTemplate == -1)
  {
    alert('Freeance Internal Error:  Unable to Print.\nReason:  No print configurations have been defined.');
  }
  else
  {
    this.loadLegendSync();
    this.setWaiting(true);
    placeholderVariables[0] = Array('legendImage',this.legendImage.src);
    if (this.vmapImage!=null)
      placeholderVariables[1] = Array('vmapImage',this.vmapImage.imageNode.src);
    else
      placeholderVariables[1] = Array('vmapImage',GuiWidget.THEME_PATH+'/'+GuiWidget.THEME+'/images/blank.gif');
    if (arguments.length > 0)
    {
      for (var i=0;i<arguments[0].length;i++)  //process placeholders
      {
        placeholderVariables[i+2] = Array(arguments[0][i][0],arguments[0][i][1]);
      }
    }
    var xmlrpcResponse = makeASyncPostRequest(this,'printMap',XMLRPC_URL,'PDFPrint.Template.Map',this.config.printConfig.templates[this.config.printConfig.activeTemplate].templateName,placeholderVariables,document.sessionID,0,document.mapObject.mapImage.width(),document.mapObject.mapImage.height(),5);
  }
};
};
/*--=-=-=-=--=---=-=-=-=-=-=-=-=-
      Deprecated functions
-==-=-=-=-=-=-=-=-==-=-=--=-=-=-*/

