document.bufferControl = new (function (id, mapObject, resultTarget)
{
  this.id = id;
  var $_this = this;
  if (!mapObject)
    mapObject = document.mapObject;
  mapObject.bufferControl = this;
  var mapLayers = mapObject.config.themes;
  this.resultTarget = resultTarget;
  this.activeTheme = '';
  this.activeSelection = '';
  this.buffers = new Object;
  this.lastThemeBuffered = '';
  this.eventHandlers={
    bufferSubmit:[],
    bufferReturn:[],
    exportSubmit:[],
    exportReturn:[],
    clearSubmit:[],
    clearReturn:[],
    clearallSubmit:[],
    clearallReturn:[]
  };
  
mapObject.addCursorEventHandler('click','BufferXY',function(xPos,yPos,width,height,XPercent,YPercent,clickMode){
  var mapImage = mapObject.mapImage;
  var bufferTheme=$_this.getActiveTheme();
  if(bufferTheme.split('-')[0] == 'group'){
    mapObject.setWaiting(true);
    
    var bufferGroup = bufferTheme.split('-')[1];
    var layers = $_this.bufferGroups[bufferGroup].group;
    var bufferlayer = $_this.bufferGroups[bufferGroup].bufferlayer;
    var bid = parseInt(bufferlayer);
    var bufferOptions = mapLayers[bid].bufferOptions;
    var bufferSqlParams = new Array();
    if(bufferOptions.sqlParams)
    {
      var sqlOptions = bufferOptions.sqlParams;
      for(var pos=0;pos<sqlOptions.length;pos++)
      {
        var fieldPairs = Array();
        for(var lcv=0;lcv < sqlOptions[pos].fieldList.length;lcv++)
        {
          var field=sqlOptions[pos].fieldList[lcv];
          fieldPairs.push([field["fieldName"],field["pdqFieldName"]]);
        }
        bufferSqlParams[pos] = [sqlOptions[pos].pdqIdentifier,fieldPairs];
        if (sqlOptions[pos].queryType != '')
        {
          bufferSqlParams[pos][2] = [
            sqlOptions[pos].queryType,
            sqlOptions[pos].numRows,
            sqlOptions[pos].startAt
          ];
        }
      }
    }
    var bufferFields = bufferOptions.fieldList;
    var bufferThemeStylesheet = (bufferOptions.areaStyleSheet)?[bufferOptions.styleSheet,bufferOptions.areaStyleSheet]:bufferOptions.styleSheet;
    
    var selectThemes = $_this.bufferGroups[bufferGroup].group;
    var selectThemesFields = [];
    var selectThemesStylesheets = [];
    
    var dist = $_this.getDistance();
    
    var selectSqlParams = [];
    for(var layer in layers){
      if(layer == 'toJSONString')
        continue;
      var bufferOptions = mapLayers[layers[layer]].bufferOptions;
      selectSqlParams.push([]);
      if(bufferOptions.sqlParams)
      {
        var sqlOptions = bufferOptions.sqlParams;
        for(var pos=0;pos<sqlOptions.length;pos++)
        {
          var fieldPairs = Array();
          for(var lcv=0;lcv < sqlOptions[pos].fieldList.length;lcv++)
          {
            var field=sqlOptions[pos].fieldList[lcv];
            fieldPairs.push([field["fieldName"],field["pdqFieldName"]]);
          }
          selectSqlParams[selectSqlParams.length-1][pos] = [sqlOptions[pos].pdqIdentifier,fieldPairs];
          if (sqlOptions[pos].queryType != '')
          {
            selectSqlParams[selectSqlParams.length-1][pos][2] = [
              sqlOptions[pos].queryType,
              sqlOptions[pos].numRows,
              sqlOptions[pos].startAt
            ];
          }
        }
      }
      selectThemesStylesheets.push(bufferOptions.styleSheet);
      selectThemesFields.push(bufferOptions.fieldList);
    }
	
    freeance_request(
      function(data){
        $_this.bufferGroup_callback(data,bufferTheme);
      },
      'GIS.Buffer.Themes.on.Point',
      mapObject.sessionID,
      0,
      width,
      height,
      XPercent, 
      YPercent,
      true,
      bufferlayer,
      bufferFields,
      bufferThemeStylesheet,
      bufferSqlParams,
      selectThemes,
      selectThemesFields,
      selectThemesStylesheets,
      dist,
      true,
      bufferOptions.maxSelect,
      selectSqlParams);
  }
  else{
    var bufferOptions = mapLayers[bufferTheme].bufferOptions;
    var sqlParams = new Array();
    if(bufferOptions.sqlParams)
    {
      var sqlOptions = bufferOptions.sqlParams;
      for(var pos=0;pos<sqlOptions.length;pos++)
      {
        var fieldPairs = Array();
        for(var lcv=0;lcv < sqlOptions[pos].fieldList.length;lcv++)
        {
          var field=sqlOptions[pos].fieldList[lcv];
          fieldPairs.push([field["fieldName"],field["pdqFieldName"]]);
        }
        sqlParams[pos] = [sqlOptions[pos].pdqIdentifier,fieldPairs];
        if (sqlOptions[pos].queryType != '')
        {
          sqlParams[pos][2] = [
            sqlOptions[pos].queryType,
            sqlOptions[pos].numRows,
            sqlOptions[pos].startAt
          ];
        }
      }
    }
    //set stylesheet param to array if an area style exists
    var stylesheet=(bufferOptions.areaStyleSheet)?[bufferOptions.styleSheet,bufferOptions.areaStyleSheet]:bufferOptions.styleSheet;
    var dist=$_this.getDistance();
    mapObject.setWaiting(true);
    freeance_request(
      function(data){
        mapObject.setWaiting(false);
        $_this.buffer_callback(data,bufferTheme);
      },
      'GIS.Buffer.at.XY',
      mapObject.sessionID,
      0,
      width,
      height,
      XPercent,
      YPercent,
      true,
      bufferTheme,
      dist,
      bufferOptions.fieldList,
      true,
      stylesheet,
      bufferOptions.maxSelect,
      sqlParams);
  }
  var events = $_this.eventHandlers['bufferSubmit'];
  for (var i=0;i<events.length;i++){
    if(events[i]){events[i](bufferTheme,dist);}
  };
});

this.createFromSelection=function(lyrid,dist,units,selectlyr,selectidx){
  //dprintf('bufferControl.createFromSelection('+lyrid+','+dist+','+units+','+selectlyr+','+selectidx+')');
  if(lyrid.split('-')[0] != 'group'){
    if(typeof(document.selectionControl.selections[selectlyr][selectidx])=='undefined'){
      return false;
    };
    mapObject.setWaiting(true);
    var selhnd=document.selectionControl.selections[selectlyr][selectidx]['handle'];
    var mapunit = document.applicationConfig.mapUnits;
    if(units!=mapunit){
      dist=convertDistance(dist,units,mapunit);
    }
    var mapImage = mapObject.mapImage;
    var bufferOptions = mapLayers[lyrid].bufferOptions;
    var sqlParams = new Array();
    if(bufferOptions.sqlParams)
    {
      var sqlOptions = bufferOptions.sqlParams;
      for(var pos=0;pos<sqlOptions.length;pos++)
      {
        var fieldPairs = Array();
        for(var lcv=0;lcv < sqlOptions[pos].fieldList.length;lcv++)
        {
          var field=sqlOptions[pos].fieldList[lcv];
          fieldPairs.push([field["fieldName"],field["pdqFieldName"]]);
        };
        sqlParams[pos] = [sqlOptions[pos].pdqIdentifier,fieldPairs];
        if (sqlOptions[pos].queryType != '')
        {
          sqlParams[pos][2] = [
            sqlOptions[pos].queryType,
            sqlOptions[pos].numRows,
            sqlOptions[pos].startAt
          ];
        }
      }
    };
    var stylesheet=(bufferOptions.areaStyleSheet)?[bufferOptions.styleSheet,bufferOptions.areaStyleSheet]:bufferOptions.styleSheet;
    freeance_request(function(data){$_this.buffer_callback(data,lyrid);},'GIS.Buffer.on.Selection',mapObject.sessionID,0,mapImage.width(),mapImage.height(),selhnd,selectlyr,lyrid,dist,bufferOptions.fieldList,true,stylesheet,bufferOptions.maxSelect,sqlParams);
    var events = this.eventHandlers['bufferSubmit'];
    for (var i=0;i<events.length;i++){
      if(events[i]){events[i](lyrid,dist,selectlyr,selectidx);}
    }
  }
  else{
    mapObject.setWaiting(true);
    var selhnd=document.selectionControl.selections[selectlyr][selectidx]['handle'];
    var mapunit = document.applicationConfig.mapUnits;
    if(units!=mapunit){
      dist=convertDistance(dist,units,mapunit);
    }
    var bufferGroup = lyrid.split('-')[1];
    var layers = $_this.bufferGroups[bufferGroup].group;
    var bufferlayer = $_this.bufferGroups[bufferGroup].bufferlayer;
    var bid = parseInt(bufferlayer);
    var bufferOptions = mapLayers[bid].bufferOptions;
    var bufferSqlParams = new Array();
    if(bufferOptions.sqlParams)
    {
      var sqlOptions = bufferOptions.sqlParams;
      for(var pos=0;pos<sqlOptions.length;pos++)
      {
        var fieldPairs = Array();
        for(var lcv=0;lcv < sqlOptions[pos].fieldList.length;lcv++)
        {
          var field=sqlOptions[pos].fieldList[lcv];
          fieldPairs.push([field["fieldName"],field["pdqFieldName"]]);
        }
        bufferSqlParams[pos] = [sqlOptions[pos].pdqIdentifier,fieldPairs];
        if (sqlOptions[pos].queryType != '')
        {
          bufferSqlParams[pos][2] = [
            sqlOptions[pos].queryType,
            sqlOptions[pos].numRows,
            sqlOptions[pos].startAt
          ];
        }
      }
    }
    var bufferFields = bufferOptions.fieldList;
    var bufferThemeStylesheet = (bufferOptions.areaStyleSheet)?[bufferOptions.styleSheet,bufferOptions.areaStyleSheet]:bufferOptions.styleSheet;
    
    var selectThemes = $_this.bufferGroups[bufferGroup].group;
    var selectThemesFields = [];
    var selectThemesStylesheets = [];
    
    var selectSqlParams = [];
    for(var layer in layers){
      if(layer == 'toJSONString')
        continue;
      var bufferOptions = mapLayers[layers[layer]].bufferOptions;
      selectSqlParams.push([]);
      if(bufferOptions.sqlParams)
      {
        var sqlOptions = bufferOptions.sqlParams;
        for(var pos=0;pos<sqlOptions.length;pos++)
        {
          var fieldPairs = Array();
          for(var lcv=0;lcv < sqlOptions[pos].fieldList.length;lcv++)
          {
            var field=sqlOptions[pos].fieldList[lcv];
            fieldPairs.push([field["fieldName"],field["pdqFieldName"]]);
          }
          selectSqlParams[selectSqlParams.length-1][pos] = [sqlOptions[pos].pdqIdentifier,fieldPairs];
          if (sqlOptions[pos].queryType != '')
          {
            selectSqlParams[selectSqlParams.length-1][pos][2] = [
              sqlOptions[pos].queryType,
              sqlOptions[pos].numRows,
              sqlOptions[pos].startAt
            ];
          }
        }
      }
      selectThemesStylesheets.push(bufferOptions.styleSheet);
      selectThemesFields.push(bufferOptions.fieldList);
    }

	var mapImage = mapObject.mapImage;
	
  freeance_request(function(data){$_this.bufferGroup_callback(data,lyrid);},'GIS.Buffer.Themes.on.Selection',mapObject.sessionID,0,mapImage.width(),mapImage.height(),selhnd,selectlyr,
      bufferlayer,
      bufferFields,
      bufferThemeStylesheet,
      bufferSqlParams,
      selectThemes,
      selectThemesFields,
      selectThemesStylesheets,
      dist,
      true,
      bufferOptions.maxSelect,
      selectSqlParams);
  }
};

this.buffer_callback=function(clientReply,layerid){
  if (resultTarget.scrollHandler!=null)  resultTarget.scrollHandler.cleanup();
  resultTarget.scrollTop = 0;
  if(clientReply.XMLRPC_FAULT)
  {
    switch (parseInt(clientReply.XMLRPC_FAULT_CODE))
    {
      case 1018:  //no results found
        /* Check to see if this theme wants to export the buffer data to CSV */
        var templateSpecialRequests = {};
        if (mapObject.config.themes[layerid].bufferOptions['export'].csv.enabled==true)
          templateSpecialRequests["includeExportBufferToCSV"] = true;
        var source = document.getTemplate(mapObject.config.themes[layerid].bufferOptions.invalidTemplate,false,templateSpecialRequests);
        resultTarget.innerHTML = source.run([[]]);
        this.buffers[layerid] = null;  //remove buffer handle...
        mapObject.redraw();  //repaint to remove any old buffer from screen
        break;
      default:
        alert('An Error Occurred in a Buffer Operation:\nError Code:  '+clientReply.XMLRPC_FAULT_CODE+'\nError Message:  '+clientReply.XMLRPC_FAULT_MESSAGE);
        break;
    }
  }
  else
  {
    var data = clientReply.data;
    this.lastThemeBuffered = layerid;
    var templateName = mapObject.config.themes[layerid].bufferOptions.resultTemplate;
    var templateData = data[2];
    
    //modify template data to account for 1:n results in chained queries.
    //builds multiple rows containing the chained different query records for the same ims data
    var cleanData = new Array();
    for (var i=0;i<templateData.length;i++)
    {
      var current_result = templateData[i];
	  cleanData[i] = new Array();
      if (current_result[1])
      {
        if ((current_result[1].length==0)||(current_result[1].length==null)){
          cleanData[i][0] = current_result[0];
        }
        else{
		  cleanData[i][0] = current_result[0];
		  for (var chainedResult in current_result[1][0]){
			cleanData[i][0][chainedResult] = current_result[1][0][chainedResult];
		  }
        }
      }
      else{
        cleanData[i][0] = current_result[0];
      }
    };
    this.buffers[layerid] = [data[1],cleanData];  //handle, queryData
    
    /* Check to see if this theme wants to export the buffer data to CSV */
    var templateSpecialRequests = {};
    if (mapObject.config.themes[layerid].bufferOptions['export'].csv.enabled==true)
      templateSpecialRequests["includeExportBufferToCSV"] = true;

    var source = document.getTemplate(templateName,false,templateSpecialRequests);
    resultTarget.innerHTML = source.run(cleanData);

    //build scrollable table
    var tables = resultTarget.getElementsByTagName('TABLE');
    if ((tables.length>0)&&(!xOp7Up)){
      var header = new ScrollableTable(tables[0],resultTarget,-2);
    }
  }
  var handle=null;
  if(data)
    handle=data[1];
  if(!tables)
    table=null;
  else
    table=tables[0];
  var events = this.eventHandlers['bufferReturn'];
  for (var i=0;i<events.length;i++){
    if(events[i]){events[i](handle,cleanData,layerid,table);}
  };
  mapObject.callback(clientReply,'BufferXY',true);
};

this.bufferGroup_callback=function(clientReply, group){
  if (resultTarget.scrollHandler!=null)  
    resultTarget.scrollHandler.cleanup();
  resultTarget.scrollTop = 0;
  if(clientReply.XMLRPC_FAULT)
  {
    switch (parseInt(clientReply.XMLRPC_FAULT_CODE))
    {
      case 1018:  //no results found
        /* Check to see if this theme wants to export the buffer data to CSV */
        var templateSpecialRequests = {};
        if (mapObject.config.themes[layerid].bufferOptions['export'].csv.enabled==true)
          templateSpecialRequests["includeExportBufferToCSV"] = true;
        var source = document.getTemplate(mapObject.config.themes[layerid].bufferOptions.invalidTemplate,false,templateSpecialRequests);
        resultTarget.innerHTML = source.run([[]]);
        this.buffers[layerid] = null;  //remove buffer handle...
        mapObject.redraw();  //repaint to remove any old buffer from screen
        break;
      default:
        alert('An Error Occurred in a Buffer Operation:\nError Code:  '+clientReply.XMLRPC_FAULT_CODE+'\nError Message:  '+clientReply.XMLRPC_FAULT_MESSAGE);
        break;
    }
  }
  else
  {
    var data = clientReply.data;
	var fullHTML = '';
	var dataCache = [];
	for(var i = 0; i < data.length-1; i++){
      this.lastThemeBuffered = data[i][0];
      var templateName = mapObject.config.themes[this.lastThemeBuffered].bufferOptions.resultTemplate;
      var templateData = data[i][2];
    
      //modify template data to account for 1:n results in chained queries.
      //builds multiple rows containing the chained different query records for the same ims data
      var cleanData = new Array();
      for (var j=0;j<templateData.length;j++){
        var current_result = templateData[j];
	    cleanData[j] = new Array();
        if (current_result[1]){
          if ((current_result[1].length==0)||(current_result[1].length==null)){//no chained query results are present.
            cleanData[j][0] = currentResult[0];
          }
          else{ //one or more chained query rows have been returned
		    cleanData[j][0] = current_result[0];
		    for (var chainedResult in current_result[1][0]){
			  cleanData[j][0][chainedResult] = current_result[1][0][chainedResult];
		    }
          }
        }
        else{
          cleanData[j][0] = current_result[0];
        }
      }
      /* Check to see if this theme wants to export the buffer data to CSV */
      var templateSpecialRequests = {};
      if (mapObject.config.themes[this.lastThemeBuffered].bufferOptions['export'].csv.enabled==true)
        templateSpecialRequests["includeExportBufferToCSV"] = true;

      var source = document.getTemplate(templateName,false,templateSpecialRequests);
	  fullHTML += source.run(cleanData);
	  dataCache.push([data[1],cleanData]);
	}
	resultTarget.innerHTML = fullHTML;
	
	this.lastThemeBuffered = group;
    this.buffers[this.lastThemeBuffered] = dataCache;
    clientReply.data = [data[data.length-1]];
  }
  setBottomPanel('searchResultPanel');
  mapObject.setWaiting(false);
  mapObject.callback(clientReply,'BufferXY',true);
};

this.exportToCSV = function()
{
  var $_this = this;
  if (this.buffers[this.lastThemeBuffered] == null) return;
  if(this.lastThemeBuffered.split('-')[0] != 'group'){
    var bufferData = this.buffers[this.lastThemeBuffered][1];
    if (bufferData.length == 0) return;
    var config = mapObject.config.themes[this.lastThemeBuffered]["bufferOptions"]["export"];
    if (!config) return;
  
    var fieldNames = new Array();
    var data = new Array();
    var ifn = config.csv.includeFieldNames; // includeFieldNames
    for(var rslt=0;rslt < bufferData.length;rslt++)
    {
      data[rslt] = new Array();
      /* start with shape file fields */
      for(var fieldName in bufferData[rslt][0]){
        if ((fieldName != '_SHAPE_')&&(fieldName!='toJSONString')&&(fieldName != '_ARCIMS_SHAPE_')){
          data[rslt].push(escapeHTML(bufferData[rslt][0][fieldName]));
          if(ifn){
            if (rslt==0){  //first column in first row cannot be named "id" - will break Excel
              if(fieldName.toLowerCase()=='id')
                fieldNames.push('ID_');
              else
                fieldNames.push(fieldName);
            }
          }
        }
      }
      /* Now with the chained queries */
      for(var cq=1;cq < bufferData[rslt].length;cq++){
        for(var fieldName in bufferData[rslt][cq][0]) // just result 0 of the chained query
        {
          if(fieldName=='toJSONString')continue;
          data[rslt].push(escapeHTML(bufferData[rslt][cq][0][fieldName]));
          if(ifn){
            if (rslt==0){  //first column in first row cannot be named "id" - will break Excel
              if(fieldName.toLowerCase()=='id')
                fieldNames.push('ID_');
              else
                fieldNames.push(fieldName);
            }
          }
        }
      }
    }
  }
  else{
    var buffersData = this.buffers[this.lastThemeBuffered];
    if (buffersData.length == 0) return;
	var bufferGroup = this.lastThemeBuffered.split('-')[1];
	var layers = this.bufferGroups[bufferGroup].group;
	var data = [];
	
	for(var layeridx in layers){
	  dataGroup = [];
	  if(layeridx == 'toJSONString')
	    continue;
	  var bufferData = buffersData[layeridx][1];
	  var layer = layers[layeridx];
      var config = mapObject.config.themes[layer]["bufferOptions"]["export"];
      if (!config) continue;
  
      var fieldNames = [];
      var ifn = config.csv.includeFieldNames; // includeFieldNames
      for(var rslt=0;rslt < bufferData.length;rslt++)
      {
	    var row = [];
        /* start with shape file fields */
        for(var fieldName in bufferData[rslt][0]){
          if ((fieldName != '_SHAPE_')&&(fieldName!='toJSONString')&&(fieldName != '_ARCIMS_SHAPE_')){
            row.push(escapeHTML(bufferData[rslt][0][fieldName]));
            if(ifn){
              if (rslt==0){  //first column in first row cannot be named "id" - will break Excel
                if(fieldName.toLowerCase()=='id')
                  fieldNames.push('ID_');
                else
                  fieldNames.push(fieldName);
              }
            }
          }
        }
        /* Now with the chained queries */
        for(var cq=1;cq < bufferData[rslt].length;cq++){
          for(var fieldName in bufferData[rslt][cq][0]) // just result 0 of the chained query
          {
            if(fieldName=='toJSONString')continue;
            row.push(escapeHTML(bufferData[rslt][cq][0][fieldName]));
            if(ifn){
              if (rslt==0){  //first column in first row cannot be named "id" - will break Excel
                if(fieldName.toLowerCase()=='id')
                  fieldNames.push('ID_');
                else
                  fieldNames.push(fieldName);
              }
            }
          }
        }
		dataGroup.push(row);
      }
	  if(fieldNames.length > 0)
	    dataGroup.unshift(fieldNames);
	  data = data.concat(dataGroup);
	}
	fieldNames = [];
  }
  mapObject.setWaiting(true);
  freeance_request(function(data){$_this.export_callback(data);},'Exporter.toCSV',config.csv.delim,data,false,fieldNames);
  var events = this.eventHandlers['exportSubmit'];
  for (var i=0;i<events.length;i++){
    if(events[i]){events[i]();}
  };
};

this.export_callback=function(clientReply){
  mapObject.setWaiting(false);
  if(clientReply.XMLRPC_FAULT)
    alert(this.id+'.callback:  clientReply fault:\n\n'+clientReply.XMLRPC_FAULT_CODE+'\n'+clientReply.XMLRPC_FAULT_MESSAGE);
  else
    downloadFile(clientReply.data);
  var events = this.eventHandlers['exportReturn'];
  for (var i=0;i<events.length;i++){
    if(events[i]){events[i](clientReply.data);}
  };
};

this.clearLayer=function(lyrid){
  if(this.buffers[lyrid]){
    handle=this.buffers[lyrid][0];
    if(handle!=null){
      var mapImage = mapObject.mapImage;
      mapObject.setWaiting(true);
      if(lyrid.split('-')[0] == 'group'){
        freeance_request(function(data){$_this.clearLayer_callback(data,lyrid,handle);},
          'GIS.Buffer.clear.AllThemes',
          mapObject.sessionID,0,
          mapImage.width(),mapImage.height());
      }
      else{
        freeance_request(function(data){$_this.clearLayer_callback(data,lyrid,handle);},
          'GIS.Buffer.clear.FromTheme',
          mapObject.sessionID,0,
          lyrid, handle, 
          mapImage.width(),mapImage.height());
      }
      var events = this.eventHandlers['clearSubmit'];
      for (var i=0;i<events.length;i++){
        if(events[i]){events[i](lyrid,handle);}
      }
    }
  }
};

this.clearLayer_callback=function(clientReply,lyrid,handle){
  mapObject.setWaiting(false);
  if(clientReply.XMLRPC_FAULT)
  {
    alert('An error occurred when clearing buffers from a map layer:  clientReply fault:\n\n'+clientReply.XMLRPC_FAULT_CODE+'\n'+clientReply.XMLRPC_FAULT_MESSAGE);
  }
  else{
    this.buffers[lyrid][0] = null;  //do not remove data, may still need csv export
    mapObject.callback(clientReply,'clearThemeBuffer',true);
  };
  //if (this.onBufferClear)
  //this.onBufferClear(handle);
  var events = this.eventHandlers['clearReturn'];
  for (var i=0;i<events.length;i++){
    if(events[i]){events[i](lyrid,handle);}
  };
};

this.clear_all=function(){
  mapObject.setWaiting(true);
  var mapImage = mapObject.mapImage;
  freeance_request(function(data){$_this.clearAll_callback(data);},'GIS.Buffer.clear.AllThemes',    mapObject.sessionID,0,mapImage.width(),mapImage.height());
  var events = this.eventHandlers['clearallSubmit'];
  for (var i=0;i<events.length;i++){
    if(events[i]){events[i]();}
  };
};

this.clearAll_callback=function(data){
  mapObject.setWaiting(false);
  mapObject.callback(data,'clearThemeBuffer',true);
  //if(this.onBufferClear)
  //  this.onBufferClear();
  var events = this.eventHandlers['clearallReturn'];
  for (var i=0;i<events.length;i++){
    if(events[i]){events[i]();}
  };
};

this.getDistance = function()
{
  var newDistance = Math.abs(parseFloat($('bufferToolRadiusInput').value));
  newDistance = isNaN(newDistance)?0:newDistance;
  $('bufferToolRadiusInput').value = newDistance;
  if(newDistance==0)
    newDistance = 0.0001; //0 will cause an error
  var bufferUnits = $('bufferToolDistanceUnitInput').value;
  if (document.mapObject.sessionID!=null){
    newDistance =convertDistance(newDistance,bufferUnits,document.applicationConfig.mapUnits);
  };
  return newDistance;
};

this.getActiveTheme = function()
{
  return $('mapBufferActiveTheme').value;
};
this.addEventHandler = function(eventType,callback)
{
  //console.assert((typeof(callback)=='function'),'Buffer Control:  attempting to add an invalid event handler for event "'+eventType+'"');  
  if (this.eventHandlers[eventType]!=null)  //empty array can eval to false
    this.eventHandlers[eventType].push(callback);
  return this.eventHandlers[eventType].length-1;
};
this.removeEventHandler = function(eventType,index)
{
  if (this.eventHandlers[eventType]!=null)  //empty array can eval to false
    this.eventHandlers[eventType][index]=null;
};

this.updateLayerList = function(){
	var themeData = document.mapObject.config.themes;
	var htmlString = '<select id="mapBufferActiveTheme">';
	var bufferable_layers = 0;
	for (var currentTheme in themeData){
		if(currentTheme=='toJSONString')continue;
			if (themeData[currentTheme].bufferOptions != null && themeData[currentTheme].visibility){
				htmlString+='<option value="'+currentTheme+'"'+((document.mapObject.config.activeTheme==currentTheme)?('selected'):(''))+'>'+themeData[currentTheme].themeName+'</option>';
				bufferable_layers++;
			}
	}
	for(var grp in document.bufferControl.bufferGroups){
		if(grp == 'toJSONString') 
			continue;
		htmlString+='<option value="group-'+grp+'">'+document.bufferControl.bufferGroups[grp].name+'</option>';
		bufferable_layers++;
	}
	if(bufferable_layers == 0){
		htmlString+= '<option value="">-- No bufferable layers visible --</option>';
	}
	htmlString+='</select>';
	$('bufferToolThemeContainer').innerHTML = htmlString;
};
})('map0BufferControl', document.mapObject, $('searchResultPanel'));

if (Freeance_BundleExtension_Manager)
	Freeance_BundleExtension_Manager.register('buffer',function(){
		if (!document.mapObject.buffersExist)
			return;
		/***  If the map has bufferable themes, include a buffer button on the toolbar  ***/
		//dprintf('bufferControl registration function');
		//document.bufferControl = new BufferControl();
		var bufferControl = document.bufferControl;
		document.bufferControl.bufferGroups = document.freeance_config_parser.parseBufferGroupConfig();
		bufferControl.addEventHandler('bufferReturn',function(){setBottomPanel('searchResultPanel');});
		bufferControl.addEventHandler('clearReturn',function(){setBottomPanel('mapToolOptionPanel');});
		/**  SET UP BUFFER FROM POINT TOOLS **/
		var bufferButton = (document.mapToolbar.showButton('bufferButton'))?document.mapToolbar.getButton('bufferButton'):document.mapToolbar.addButton('bufferButton',ToolBar.BUTTON_RADIO,ToolBar.ADD_BUTTON_LAST,null,25,25,75,true,'toolBar.png','Buffer Features',mapCursorRadioButtonGroup,'');
		bufferButton.clickEvent = function () 
		{
			var themeData = document.mapObject.config.themes;
			var htmlString = '<select id="mapBufferActiveTheme">';
			var bufferable_layers = 0;
			for (var currentTheme in themeData){
				if(currentTheme=='toJSONString')continue;
					if (themeData[currentTheme].bufferOptions != null && themeData[currentTheme].visibility){
						htmlString+='<option value="'+currentTheme+'"'+((document.mapObject.config.activeTheme==currentTheme)?('selected'):(''))+'>'+themeData[currentTheme].themeName+'</option>';
						bufferable_layers++;
					}
			}
			for(var grp in document.bufferControl.bufferGroups){
				if(grp == 'toJSONString') 
					continue;
				htmlString+='<option value="group-'+grp+'">'+document.bufferControl.bufferGroups[grp].name+'</option>';
				bufferable_layers++;
			}
			if(bufferable_layers == 0){
				htmlString+= '<option value="">-- No bufferable layers visible --</option>';
			}
			htmlString+='</select>';
			$('bufferToolThemeContainer').innerHTML = htmlString;
			
			var updateMsg = function(){
				var themeData = document.mapObject.config.themes;
				var theme = $('mapBufferActiveTheme').value;
				
				if(theme == ''){
					$('bufferToolTimeWarning').style.display='none';
					return;
				}
				
				if(theme.split('-')[0] == "group" || themeData[theme].bufferOptions.sqlParams){
					$('bufferToolTimeWarning').style.display='block';
				}
				else{
					$('bufferToolTimeWarning').style.display='none';
				}
			};
			xAddEventListener($('mapBufferActiveTheme'),'change',updateMsg);
			updateMsg();
			
			document.mapObject.mapImage.setMouseMode('BufferXY');
			setActiveMapTool('BufferXY');
			$('mapToolPanelNameField').innerHTML = 'Buffer Feature';
		};
		/** SET UP BUFFER FROM SELECTION TOOLS **/
		$("selectionBufferOptionContainer").style.display = 'block';
		var bufferSelectString = '<select id="selectionBufferThemeSelector">';
		for (var currentTheme in document.mapObject.config.themes){
			if(currentTheme=='toJSONString')continue;
			if (document.mapObject.config.themes[currentTheme].bufferOptions != null)
				bufferSelectString+='<option value="'+currentTheme+'">'+document.mapObject.config.themes[currentTheme].themeName+'</option>';
		}
		for(var grp in document.bufferControl.bufferGroups){
			if(grp == 'toJSONString') 
				continue;
			bufferSelectString+='<option value="group-'+grp+'">'+document.bufferControl.bufferGroups[grp].name+'</option>';
		}
		bufferSelectString+='</select>';
		$('selectionBufferThemeSelectContainer').innerHTML = bufferSelectString;
		document.runBufferFromSelection = function()
		{
			//dprintf('document.runBufferFromSelection');
			var dist=parseFloat($('selectionBufferDistanceInput').value);
			if(isNaN(dist))
			dist=0;
			document.bufferControl.createFromSelection(
			$('selectionBufferThemeSelector').value,
			parseFloat($('selectionBufferDistanceInput').value),
			$('selectionBufferDistanceUnitInput').value,
			document.selectionControl.displaylyr,
			document.selectionControl.displaysid);
		};
		var tempimg = document.createElement("DIV");
		var tempimage = document.createElement("IMG");
		tempimg.appendChild(tempimage);
		tempimg.style.overflow = 'hidden';
		tempimg.style.height = 15;
		tempimage.style.position = 'relative';
		tempimage.style.top = -30;
		tempimage.src = './'+GuiWidget.THEME_PATH+'/'+GuiWidget.THEME+'/images/icon.png';
		return true;
	});
