BufferPanel = function (newId, newParent, newXPosition, newYPosition, newZIndex, newWidth, newHeight, newVisibility, newMapObject, newMapId, newResultTarget)
{
  if (arguments.length > 0)
    this.init(newId, newParent, newXPosition, newYPosition, newZIndex, newWidth, newHeight, newVisibility, newMapObject, newMapId, newResultTarget);
};

BufferPanel.prototype = new GuiWidget();
BufferPanel.constructor = BufferPanel;
BufferPanel.superclass = GuiWidget.prototype;
 
BufferPanel.prototype.init = function (newId, newParent, newXPosition, newYPosition, newZIndex, newWidth, newHeight, newVisibility,newMapObject, newMapId, newResultTarget)
{
  BufferPanel.superclass.init.call(this, newId, newParent, newXPosition, newYPosition, newZIndex, newWidth, newHeight, newVisibility, "");
  this.id = newId;

  if (newMapId!=null)
  {
    this.mapObject = OBJECT_MANAGER.getControl(newMapId);
    this.mapId = newMapId;
  }
  else
  {
    this.mapObject = newMapObject;
    this.mapId = newMapObject.id;
  }
  
  this.mapObject.bufferControl = this;
  this.resultTarget = newResultTarget;
  this.activeTheme = '';
  this.activeSelection = '';
  this.buffers = new Array();

  this.bufferConfig = new Object;
  this.activeQuery = null;          //currently active buffer query (if any)
  this.bufferRadioButtonGroup = null;
  this.enabled = false;
  
  this.lastThemeBuffered = '';
};

BufferPanel.prototype.initialize = function(numThemes)
{
  //numThemes is the number of bufferable themes.
  //if 0, draw a panel indicating that buffers are disabled
  if (numThemes > 0)
  {
    this.draw();
    this.enabled = true;
  }
  else
  {
    this.enabled = false;
    this.drawDisabled();
  }
};

BufferPanel.prototype.drawDisabled = function()
{
  this.simplePanelWidget = new GuiWidget(this.id+"themeElement", this.element, 0, 0, 0, this.width(), 230, true, "");
    this.headerCaptionElement = new GuiWidget(this.id+"headerCaptionElement", this.simplePanelWidget.element, 0, 0, 0, this.width(), 20, true, "themeGroupHeader");
    this.headerCaptionElement.element.cbe.innerHtml("Buffer Selection");
    this.formContainer = new GuiWidget (this.id+"formContainer", this.simplePanelWidget.element, 0, 20, 0, this.width(), 50, true, "QueryObjectBottom");
    this.formContainer.element.innerHTML = '<span style="color: red; font-weight: bold;">Buffer Disabled</span><br><br>No Bufferable Themes Exist.';
  this.height(75);
};

BufferPanel.prototype.draw = function()
{
  var ypos = 0;
  var htmlString = '';
  this.bufferRadioButtonGroup = this.mapObject.mapPanel.toolbarRadioButtonGroup;

   //declare a widget to contain the query panels.  This will be hidden by default
  this.queryContainer = new GuiWidget (this.id+"queryContainer", this.element, 0, 230, 0, this.width(), 50, false, "");
  this.simplePanelWidget = new GuiWidget(this.id+"themeElement", this.element, 0, 0, 0, this.width(), 230, true, "");
    this.headerCaptionElement = new GuiWidget(this.id+"headerCaptionElement", this.simplePanelWidget.element, 0, 0, 0, this.width(), 20, true, "themeGroupHeader");
    this.headerCaptionElement.element.cbe.innerHtml("Buffer Selection");
    this.formContainer = new GuiWidget (this.id+"formContainer", this.simplePanelWidget.element, 0, 20, 0, this.width(), 215, true, "QueryObjectBottom");
      this.themeSelectContainer = new GuiWidget(this.id+"themeSelectContainer", this.formContainer.element, 10, 0, 0, this.width(), 40, true, "");
        this.themeSelectHeader = new GuiWidget(this.id+"themeSelectHeader", this.themeSelectContainer.element, 0, 0, 0, this.themeSelectContainer.width()-10, 20, true, "");
        this.themeSelectHeader.element.cbe.innerHtml('Target Theme');
        this.themeSelectInputForm = new GuiWidget(this.id+"themeSelectInputForm", this.formContainer.element, 10, 20, 0, this.themeSelectContainer.width()-10, 20, true, "");
         //build select box for target themes, add query input forms as needed  
         htmlString = '<select id="'+this.id+'themeSelectFormInput" onchange="+document.getWidgetById(\''+this.id+'\').setActiveTheme(this.value);">';
          
          if (this.mapObject.config.activeTheme.bufferOptions != null)
            this.activeTheme = this.mapObject.config.activeTheme;
          else
            this.activeTheme = null;
          for (var currentTheme in this.mapObject.config.themes)
          {
            if (this.mapObject.config.themes[currentTheme].bufferOptions)
            {
              if (this.activeTheme == null)
                this.activeTheme = currentTheme;
              htmlString+= ('<option value="'+currentTheme+'" '+((currentTheme==this.activeTheme)?'selected':'')+' >'+this.mapObject.config.themes[currentTheme].themeName+'</option>');
              this.buffers[currentTheme] = null;
                //create an object for each bufferable theme containing configuration data
                //will also contain pointers to the query panels.
                //indexed by theme name.
                this.bufferConfig[currentTheme] = this.mapObject.config.themes[currentTheme].bufferOptions;
                if (this.bufferConfig[currentTheme].filterQueries)
                {
                  this.bufferConfig[currentTheme].queryPanelContainer = new GuiWidget (this.id+"."+currentTheme+".queryPanelContainer", this.queryContainer.element, 0, 0, 0, this.width(), 50, false, "");
                  var queryYPos = 0;
                  for (var currentQuery in this.bufferConfig[currentTheme].filterQueries)  //build panels for individual queries
                  {
                    this.bufferConfig[currentTheme].filterQueries[currentQuery] = document.getGuiValue(currentQuery);
                    this.bufferConfig[currentTheme].filterQueries[currentQuery].queryPanel = new BufferQueryPanel(this.id+'.'+currentTheme+'.filterQueries.'+currentQuery+'.queryPanel',this.bufferConfig[currentTheme].queryPanelContainer.element,0,queryYPos,0,this.width(),50,true,this,currentTheme,currentQuery);
                    queryYPos += this.bufferConfig[currentTheme].filterQueries[currentQuery].queryPanel.height();
                  }
                  this.bufferConfig[currentTheme].queryPanelContainer.height(queryYPos);
                  if (this.queryContainer.height() < this.bufferConfig[currentTheme].queryPanelContainer.height())
                    this.queryContainer.height(this.bufferConfig[currentTheme].queryPanelContainer.height());
                  
                }
                else
                {
                  this.bufferConfig[currentTheme].queryPanelContainer = null; 
                }
            }
          }
          htmlString += '</select>';
          this.themeSelectInputForm.element.cbe.innerHtml(htmlString);
          this.activeThemeInput = document.getElementById(this.id+'themeSelectFormInput');
        this.rangeHeader = new GuiWidget(this.id+"themeSelectHeader", this.formContainer.element, 10, 45, 0, this.themeSelectContainer.width()-10, 20, true, "");
        this.rangeHeader.element.cbe.innerHtml('Buffer Radius');
        this.rangeInputForm = new GuiWidget(this.id+"rangeInputForm", this.formContainer.element, 10, 65, 0, this.themeSelectContainer.width()-10, 20, true, "");
          htmlString = '<input id="'+this.id+'rangeInput" type="text">';
          this.rangeInputForm.element.cbe.innerHtml(htmlString);
          this.rangeInput = document.getElementById(this.id+'rangeInput');
        this.pointButton = new RadioButton(this.id+"pointButton", this.formContainer.element, 10, 85, 0, 100,20,true,'bufferPointButton','',this.bufferRadioButtonGroup);
        this.pointButton.bufferPanel = this;
        this.pointButton.clickEvent = function(e)
        {
          this.bufferPanel.mapObject.mapPanel.clickMode = 'BufferXY'; 
          this.bufferPanel.activeQuery = null;
        };

        this.selectionHeader = new GuiWidget(this.id+"selectionHeader", this.formContainer.element, 10, 110, 0, this.themeSelectContainer.width()-10, 20, true, "");
        this.selectionHeader.element.innerHTML = 'Source Selection';
        this.selectionInputForm = new GuiWidget(this.id+"selectionInputForm", this.formContainer.element, 10, 130, 0, this.themeSelectContainer.width()-10, 20, true, "");
        
        //var htmlString = '<select id="'+this.id+'selectionInputFormElement" onchange="+document.getWidgetById(\''+this.id+'\').setActiveSelection(this.value);">';
        //htmlString += '<option selected value="none">None</option>';
        //htmlString += '</select>';
        //this.selectionInputForm.element.innerHTML = htmlString;
        
        this.selectionButton = new ImageButton(this.id+"selectionButton", this.formContainer.element, 10, 155, 0, 100,20,true,'bufferSelectionButton','');
        this.selectionButton.bufferPanel = this;
        this.selectionButton.clickEvent = function(e)
        {
          this.bufferPanel.bufferFromSelection(null);
        };
        
        this.clearButton = new ImageButton(this.id+"clearButton", this.formContainer.element, 10, 180, 0, 100,20,true,'clearBufferButton','');
        this.clearButton.bufferPanel = this;
        this.clearButton.clickEvent = function(e)
        {
          this.bufferPanel.clearActiveTheme(); 
        };
  this.height(this.simplePanelWidget.height()+this.queryContainer.height());
  this.setActiveTheme(this.activeTheme);
  this.buildSelectionInputForm();
};

BufferPanel.prototype.resize = function(newWidth, newHeight)
{
  this.element.cbe.resizeTo(newWidth, this.height());  
};

BufferPanel.prototype.buildSelectionInputForm = function()
{
  var htmlString = '<select id="'+this.id+'selectionInputFormElement">';
  
  htmlString += '<option selected value="none">None</option>';

  for (var currentTheme in this.mapObject.config.themes)
  {
    if (this.mapObject.config.themes[currentTheme]["selectOptions"])
    {
      htmlString += '<optgroup label="'+this.mapObject.config.themes[currentTheme].themeName+'">';
      if(this.mapObject.selectionControl.selections[currentTheme].list != null)
      {
        var currentSelection = this.mapObject.selectionControl.selections[currentTheme].list;
        while (currentSelection != null)
        {
          htmlString+= '<option value="'+currentSelection.handle+'.'+currentTheme+'">'+currentSelection.identifier+'</option>';
          currentSelection = currentSelection.next;
        }
      }
      htmlString += '</optgroup>';
    }
  }

  htmlString += '</select>';
  this.selectionInputForm.element.innerHTML = htmlString;
};

BufferPanel.prototype.updateSelections = function()
{
  //perform any operations required to update the selection list for the buffer control
  if (this.enabled)
    this.buildSelectionInputForm();
};

BufferPanel.prototype.setActiveSelection = function(newSelectionTheme, newSelectionHandle)
{
  if (this.enabled)
    document.getElementById(this.id+'selectionInputFormElement').value = (newSelectionHandle+'.'+newSelectionTheme);
};

BufferPanel.prototype.clearActiveTheme = function()
{
  if (this.buffers[this.getActiveTheme()]!= null)
    this.mapObject.clearThemeBuffer(this.getActiveTheme(),this.buffers[this.getActiveTheme()][0]);
};

BufferPanel.prototype.bufferFromSelection = function(filterQuery)
{
  //filter query is the equivalant of this.activeQuery
  var selectionFormValue = document.getElementById(this.id+'selectionInputFormElement').value;
  if (selectionFormValue != 'none')
  {
    var selectionHandle = parseInt(selectionFormValue);
    var sourceThemeOffset = selectionFormValue.indexOf(".");
    var sourceThemeId = selectionFormValue.substr(sourceThemeOffset+1,selectionFormValue.length);
    if(this.mapObject.config.themes[this.activeTheme].bufferOptions.sqlParams != null)
    {
      var configSQLParams = this.mapObject.config.themes[this.activeTheme].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 (filterQuery == null)
      var bufferSQLParams = null;
    else
    {
      var queryIndex = filterQuery.queryId;
      var dataPairs = filterQuery.getDataPairs();
      var bufferSQLParams = new Array(filterQuery.queryConfig.request.pdqIdentifier,dataPairs)
    }
    this.mapObject.bufferOnSelection(selectionHandle,sourceThemeId,this.activeTheme,this.getDistance(), sqlParams, bufferSQLParams, true);
  }
};

BufferPanel.prototype.getDistance = function()
{
  if ((this.rangeInput.value == '') || (this.rangeInput.value == null))
    return 1;
  else
    return this.rangeInput.value;
};

BufferPanel.prototype.getActiveTheme = function()
{
  return this.activeThemeInput.value;
};

BufferPanel.prototype.setActiveTheme = function(newActiveTheme)
{
  if (this.activeTheme != '')
  {
    //hide any query panels for the currently active theme
    if (this.bufferConfig[this.activeTheme].filterQueries != null)
    {
      //hide the query buffer panel
      this.bufferConfig[this.activeTheme].queryPanelContainer.hide();
      for (var currentQuery in this.bufferConfig[this.activeTheme].filterQueries)
      {
        if (this.bufferConfig[this.activeTheme].filterQueries[currentQuery].queryPanel.isActive())
        {
          this.mapObject.mapPanel.clickMode = 'BufferXY';
          this.bufferConfig[this.activeTheme].filterQueries[currentQuery].queryPanel.setInactive();
          this.pointButton.setActive();
        }
      }
    }
  }
  this.activeTheme = newActiveTheme;
  if (newActiveTheme == '')
  {
    this.activeTheme = document.getElementById(this.id+'themeSelectFormInput').value;
  }
  //display buffer queries for the selected theme
  if (this.bufferConfig[this.activeTheme].filterQueries != null)
  {
    this.bufferConfig[this.activeTheme].queryPanelContainer.show();
    this.queryContainer.show();
  }
  else
    this.queryContainer.hide();
};


BufferPanel.prototype.getSQLParams = function()
{
  //check to see if a query panel is active.
  if (this.activeQuery != null)
  {
    var queryIndex = this.activeQuery.queryId;
    var dataPairs = this.activeQuery.getDataPairs();
    var sqlParams = new Array(this.activeQuery.queryConfig.request.pdqIdentifier,dataPairs)
  }
  else
    var sqlParams = null;
  return (sqlParams);
};

BufferPanel.prototype.exportToCSV = function()
{
  return(this.exportData('csv'));
};
BufferPanel.prototype.exportToXML = function()
{
  return(this.exportData('xml'));
};


BufferPanel.prototype.exportData = function(exportType)
{
  if (this.buffers[this.lastThemeBuffered] == null)
    return;
  var bufferData = this.buffers[this.lastThemeBuffered][1];
  if (bufferData.length == 0)
    return;
  var config = this.mapObject.config.themes[this.lastThemeBuffered].bufferOptions;
  if (!config['export'])
    return;
  var fieldNames = new Array();
  var data = new Array();
  for(var lcv=0;lcv < bufferData.length;lcv++)
  {
    data[lcv] = new Array();
    colPos = 0;
    /* start with shape file fields */
    for(var fieldName in bufferData[lcv][0])
      if (fieldName != '_SHAPE_')
      {
        data[lcv][colPos++] = escapeHTML(bufferData[lcv][0][fieldName]);
        if (lcv==0)
          fieldNames.push(fieldName);
      }
    /* Now with the chained queries */
    for(var chainedQueryPos=1;chainedQueryPos < bufferData[lcv].length;chainedQueryPos++)
      for(var fieldName in bufferData[lcv][chainedQueryPos][0]) // just row 0 of the chained query
      {
        data[lcv][colPos++] = escapeHTML(bufferData[lcv][chainedQueryPos][0][fieldName]);
        if (lcv==0)
          fieldNames.push(fieldName);
      }
  }
  switch(exportType)
  {
    case 'csv':
        if ((OBJECT_MANAGER.getGuiValueById('extensions')) && (OBJECT_MANAGER.getGuiValueById('extensions')['exportBufferToCSV']) && (!OBJECT_MANAGER.getGuiValueById('extensions')['exportBufferToCSV'].enabled))
          return;
        if (config["export"].csv.enabled == false)
          return;
        var request = 'Exporter.toCSV';
        var delim = config["export"].csv.delim; // delim
        var ifn = config["export"].csv.includeFieldNames; // includeFieldNames
        if (!ifn)
          fieldNames = new Array();
        this.mapObject.setWaiting(true);
        makeASyncPostRequest(
           this,
           Array(request),
           XMLRPC_URL,
           request,
           delim,
           data,
           true,
           fieldNames
           );
        break;
  }
};

BufferPanel.prototype.callback = function(serverReplyDoc, pendingOperation)
{
  if (!validateXMLDoc(serverReplyDoc))
  {
    return null;
  }
  var clientReply = new XMLRPCResponse();
  //clientReply.setResponseByStr(serverReplyDoc.xml);
  clientReply.setResponseByDoc(serverReplyDoc);
  if(clientReply.isFault())
  {
    switch (parseInt(clientReply.getFaultCode()))
    {
      case 1018:  //no results found
        this.mapObject.callback(serverReplyDoc,pendingOperation[0]); //no elements found...
        this.mapObject.redraw();
        var templateName = this.mapObject.config.themes[pendingOperation[1]].bufferOptions.invalidTemplate;
        var templateData = new Array();
        templateData[0] = new Array();
        var source = document.getTemplate(templateName);
        this.buffers[pendingOperation[1]] = null;  //remove buffer handle...
        document.getWidgetById(this.resultTarget).element.innerHTML = source.run(templateData);
        break;
      default:
        alert(this.id+'.callback:  clientReply fault:\n\n'+clientReply.getFaultCode()+'\n'+clientReply.getFaultString());
        this.mapObject.callback(serverReplyDoc,pendingOperation[0]); //no elements found...
        break;
    }
  }
  else
    var data = clientReply.getObject();
  if (data != null)
  {
    switch (pendingOperation[0])
    {
      case 'BufferXY':
      case 'BufferOnSelection':
        this.lastThemeBuffered = pendingOperation[1];
        var templateName = this.mapObject.config.themes[pendingOperation[1]].bufferOptions.resultTemplate;
        this.buffers[pendingOperation[1]] = Array(data[1],data[2]);  //handle, queryData
        var templateData = data[2];
        var source = document.getTemplate(templateName);
        document.getWidgetById(this.resultTarget).element.innerHTML = source.run(templateData);
        this.mapObject.callback(serverReplyDoc,'BufferXY');
        break;
      case 'clearThemeBuffer':
        this.buffers[pendingOperation[1]] = null;
        this.mapObject.callback(serverReplyDoc,'clearThemeBuffer');
        break;
      case 'Exporter.toCSV':
      case 'Exporter.toXML':
        this.mapObject.setWaiting(false);
        var url = data;
        downloadFile(url);
        break;
    }
  }
};

