QueryControl = function (newId)
{
  OBJECT_MANAGER.addControl(this,'queryControl', newId);
  this.id = newId;
  this.config = null;
  this.resultTarget = null;
  this.currentQueryForm = null;
  this.currentQueryPage = 0;
  this.currentQueryId = null;
  this.currentQueryValuePairs = null;
  this.onDrawIndexForm = new Array();
  this.onDrawQueryForm = new Array();
  return;
};

QueryControl.prototype.setConfig = function(newConfig)
{
  //sets the configration to the specified data structre.
  this.config  = newConfig;
  this.shownQueries = 0;  //displayed queries
  this.totalQueries = 0;  //all queries
  for (var currentQuery in this.config)
  {
    this.totalQueries++;
    if(this.config[currentQuery].display)
      this.shownQueries++;
  }
  document.getElementById('queryBookmarkContainer').style.display = 'none';
};

QueryControl.prototype.initialize = function()
{
  //with the config and both panels set, we can now generate all contents!  this is not 
  //done automatically since it may be deferred to improve load time.
};

QueryControl.prototype.setIndexPanel = function(newIndexPanel)
{
  //set the index panel reference and do initial population.
  this.indexPanel = newIndexPanel;
};

QueryControl.prototype.drawIndexPanel = function()
{
  this.currentQueryForm = null;
  if (this.shownQueries > 1)
  {
    var htmlString = '';
    for (var currentQuery in this.config)
    {
      if(this.config[currentQuery].display)
        htmlString+='<div class="queryIndexQueryTitle"><span onclick="document.getGuiControl(\''+this.id+'\').drawFormPanel(\''+currentQuery+'\');" class="pseudolink">'+this.config[currentQuery]['title']+'</span></div><div class="queryIndexDescriptionForm">'+this.config[currentQuery]['description']+'</div>';
    }
    if (this.indexPanel != null)
    {
      this.indexPanel.innerHTML = htmlString;
    }
    document.getElementById('queryBookmarkContainer').style.display = 'none';
  }
  else
  {
    if (this.totalQueries!=0){  //accomodate case where no pdqs are present but geocode is
      for (var currentQuery in this.config)
      {
        if (this.config[currentQuery].display)
        {
          this.drawFormPanel(currentQuery);
          break;
        }
      }
    }
  }
};

QueryControl.prototype.setFormPanel = function (newFormPanel)
{
  //set the form panel reference
  this.formPanel = newFormPanel;
};

QueryControl.prototype.drawFormPanel = function(queryId)
{
  if (document.geocodeAddress||document.geocodeIntersection)
    document.getElementById('geocodeIndexContainer').style.display = 'none';
  
  this.currentQueryForm = queryId;
  if (this.currentQueryForm != null)
  {
    var htmlString = '';
    if (this.shownQueries > 1)
      htmlString +=  '<div id="queryIndexToggle" class="selectionDisplayPanelHeader" style="text-align: center;">'
      +'<span class="pseudolink" onclick="showQueryIndexPanel();">Show All Searches</span></div>';
    htmlString += '<div class="rightPanelFormHeader2">'+this.config[queryId]['title']+'</div>'
    + '<div class="queryIndexDescriptionForm"><div>'+this.config[queryId]['HTMLForm']+'<div></div>';
    if ((this.config[queryId]["export"]) && (this.config[queryId]["export"].csv) && (this.config[queryId]["export"].csv.enabled==true))
      htmlString+='<div style="text-align: center;"><span class="pseudolink" onclick="document.getGuiControl(\''+this.id+'\').runExportQuery(\''+queryId+'\',\'csv\');">Export Query to CSV</span></div>';
    if (document.savedQueryControl)
      htmlString+='<div style="text-align: center;"><span class="pseudolink" onclick="document.getGuiControl(\''+this.id+'\').saveQuery(\''+queryId+'\');">Save Query Values</span></div>';
    htmlString += '<div style="width:  auto; text-align: center;"><input type="submit" class="submitButton" value="Run Search" onclick="document.getGuiControl(\''+this.id+'\').submitQueryForm(\''+queryId+'\');"></div>';
    if (document.savedQueryControl)
    {
      document.savedQueryControl.drawSavedQueryList(queryId);
      document.getElementById('queryBookmarkContainer').style.display = 'block';
    }
    this.formPanel.innerHTML = htmlString;
    this.indexPanel.style.display = 'none';
    this.formPanel.style.display = 'block';
    
    //add enter button event to form elements
    var inputElements = this.formPanel.getElementsByTagName('input');
    for (var elementIndex=0;elementIndex<inputElements.length;elementIndex++)
    {
      inputElements[elementIndex].queryId = queryId;
      inputElements[elementIndex].queryControl = this;
      xAddEventListener(inputElements[elementIndex],'keypress',function(e){evt = new xEvent(e);if (evt.keyCode==13){evt.target.queryControl.submitQueryForm(evt.target.queryId);}});
    }
    if (this.config[queryId].suggestConfig!=null)
    {
      for (var currentSuggestIndex = 0; currentSuggestIndex < this.config[queryId].suggestConfig.length; currentSuggestIndex++)
      {
        document.SuggestControl.addSuggest(this.config[queryId].suggestConfig[currentSuggestIndex]);
      }
    }
  }
};

QueryControl.prototype.runExportQuery = function(queryId,exportType)
{
  this.exportQuery(exportType,queryId, this.getFormValues(queryId));
};

QueryControl.prototype.setResultTarget = function (newResultTarget)
{
  //set a reference to the target element for query results.
  this.resultTarget = newResultTarget;
};

QueryControl.prototype.getFormValues = function (newQueryId)
{
  var queryValuePairs = new Array();
  var variableIndex = 0;
  for (var currentFieldName in this.config[newQueryId]['fieldList'])
  {
    var valueName = currentFieldName;
    var inputElement = document.getElementById('sqlQuery.'+newQueryId+'.'+currentFieldName+'InputField');
    queryValuePairs[variableIndex] = new Array();
    queryValuePairs[variableIndex][0] = currentFieldName;
    if (inputElement != null)
    {
      var inputValue = inputElement.value;
      if (inputValue == '')
        inputValue = this.config[newQueryId]['fieldList'][currentFieldName].defaultValue;
      queryValuePairs[variableIndex][1] = inputValue;
    }
    else
      queryValuePairs[variableIndex][1] = this.config[newQueryId]['fieldList'][currentFieldName].defaultValue;
    variableIndex++;
  }
  return queryValuePairs;
};

QueryControl.prototype.submitQueryForm = function (newQueryId)
{
  //called when the submit button is clicked.
  //loop through the fields in the form and build the name/value pairs.
  //The start page will be 0 
  //firstRun will be true...
  
  //build value pairs array based on field names.  If a field can't be found, use it's default values.
  this.runQuery(newQueryId, this.getFormValues(newQueryId), 1, true);
};

QueryControl.prototype.runQuery = function(queryId, newValuePairs, newStartPage, firstRun)
{
  this.currentQueryId = queryId;
  this.currentQuery = this.config[queryId];
  this.currentSourceValuePairs = newValuePairs;
  templatehow = 'elem';

  this.currentQueryPage = newStartPage;
  this.currentQueryValuePairs = new Array();
  var valueIndex = 0;
  for (var currentValue in newValuePairs)
  {
    this.currentQueryValuePairs[valueIndex] = new Array(newValuePairs[currentValue][0],newValuePairs[currentValue][1]);
    valueIndex++;
  }
  var data = makeASyncPostRequest(
             this,
             this.currentQuery.request.requestMethod,
             XMLRPC_URL,
             this.currentQuery.request.requestMethod,
             this.currentQuery.request.pdqIdentifier,
             this.currentQuery.templates.pageRows,
             this.currentQueryPage,
             this.currentQueryValuePairs);
  if (this.loadImage != null)
    document.getWidgetById(this.loadImage).show();
  if (this.onQuerySubmit)
    this.onQuerySubmit();
};

QueryControl.prototype.exportQuery = function(exportType,queryId, newValuePairs)
{
  var queryConfig = this.config[queryId];
  var request = 'SQL.export.execute';
  var exportFormat = new Array();
  exportFormat[0] = exportType;
  exportFormat[1] = true;  // UseZip
  var queryType = 'definedQuery';
  switch(exportType)
  {
    case 'csv':
      exportFormat[2] = queryConfig["export"].csv.delim; // delim
      exportFormat[3] = queryConfig["export"].csv.includeFieldNames; // includeFieldNames
      break;
  }
  makeASyncPostRequest(this,request,XMLRPC_URL,request,exportFormat,queryType,queryConfig.request.pdqIdentifier,newValuePairs);
  document.mapObject.setWaiting(true);             
};

QueryControl.prototype.saveQuery = function (newQueryId)
{
  if (document.savedQueryControl)
  {
    var newSaveName = prompt('Enter a name for the saved query','');
    if ((newSaveName != '') && (newSaveName != null)&&(newSaveName!=false))
      document.savedQueryControl.addSavedQuery(newSaveName,newQueryId, this.getFormValues(newQueryId));
  }
};

QueryControl.prototype.loadNextPage = function()
{
  this.runQuery(this.currentQueryId,this.currentSourceValuePairs,this.currentQueryPage+1, false);
};

QueryControl.prototype.loadPreviousPage = function()
{
  this.runQuery(this.currentQueryId,this.currentSourceValuePairs,this.currentQueryPage-1, false);
};

QueryControl.prototype.zoomToResults = function(themeId,themeTargetField,queryFieldName,fieldQuotes,stylesheet)  // JPW
{
  var whereClauseArr = Array();
  var whereClauseStr = '';
  var realData = this.currentResultData[3];
  
  if (fieldQuotes)
    var quotes = "'";
  else
    var quotes = "";

  if ((realData.length == 0) || (document.mapObject.markupControl == null)) // haha very funny
  {
    if (this.loadImage != null)
      document.getWidgetById(this.loadImage).show();
    if (realData.length == 0)
      alert('No data to zoom to.');
    else
      alert('This requires the markup extension to be enabled in this application.  Please notify your system administrator.');
    if (this.loadImage != null)
      document.getWidgetById(this.loadImage).hide(); // see, it's FAST!
    return;
  }
  
  for(var lcv=0;lcv < realData.length;lcv++)
    whereClauseArr[whereClauseArr.length] = "("+themeTargetField+"="+quotes+realData[lcv][queryFieldName]+quotes+")";
  whereClauseStr = whereClauseArr.join(" or ");

  var request = 'GIS.Zoom.to.queryResults';
  var requestInfo = new Object();
  requestInfo.themeID = themeId;
  requestInfo.request = request;
  var wantReturnFields = false;
  var returnFields = '';
  var zoomFactor = 1.0;
  var maxCount = 0;  // all
  document.mapObject.setWaiting(true);
  makeASyncPostRequest(this,requestInfo,XMLRPC_URL,request,document.mapObject.sessionID,0,document.mapObject.mapImage.width(),document.mapObject.mapImage.height(),themeId,returnFields,whereClauseStr,zoomFactor,maxCount,wantReturnFields,stylesheet);
};

QueryControl.prototype.addZoomToMarkupToIndex = function(themeID,data)  // JPW
{
  var markupObj = new Object;
  markupObj.handle = data.handle;
  markupObj.themeName = themeID;
  markupObj.themeID = themeID;
  markupObj.labelName = String.stripQuotes(String.escapeHTML('Results: '+document.mapObject.config.themes[themeID].themeName));
  markupObj.markupID = String.stripQuotes(String.escapeHTML('Results: '+document.mapObject.config.themes[themeID].themeName));
  markupObj.description = String.stripQuotes(String.escapeHTML('Results: '+document.mapObject.config.themes[themeID].themeName));
  markupObj.extent = data.zoomExtent;
  markupObj.viewExtent = data.zoomExtent;
  markupObj.type = 'zoomToResults'; // i guess...
  markupObj.style = '0';
  markupObj.mode = 'zoomToResults';
  
  document.mapObject.markupControl.addToExistingMarkup(markupObj,markupObj.handle);
  document.mapObject.markupControl.drawMarkupExistingPanel();
};

QueryControl.prototype.callback = function(serverReplyDoc, requestType)
{
  if (this.resultTarget.scrollHandler!=null)
    this.resultTarget.scrollHandler.cleanup();
  var noResults = false;
  if (this.loadImage != null)
  {
    document.getWidgetById(this.loadImage).hide();
  }
  /* begin error checks */
  if (serverReplyDoc == null)
  {
    return (null);
  }
  var xmlstr = (typeof(serverReplyDoc.xml)=='function')?serverReplyDoc.xml():serverReplyDoc.xml;
  if (xmlstr == '') 
  {
    return (null);
  }
  if (serverReplyDoc.documentElement.nodeName == 'parsererror')
  {
    return (null);
  }
  var clientReply = new XMLRPCResponse();
  clientReply.setResponseByDoc(serverReplyDoc);
  if (clientReply.isFault())
  {
    var sqlData = null;
    //We're expecting this to happen, suppress certain fault messages
    if ((clientReply.getFaultCode()!=2003)&&(clientReply.getFaultCode()!=2004)&&(clientReply.getFaultCode()!=2005))
    {
      alert('An error occurred in the query operation:\n\nError Code:  '+clientReply.getFaultCode()+'\nError Message:  '+clientReply.getFaultString());
    }
    if (clientReply.getFaultCode() == 2003)  //Requested page number less than 1
      this.currentQueryPage++;
    if (clientReply.getFaultCode() == 2004)  //requested page number greater than last page
      this.currentQueryPage--;
    if (clientReply.getFaultCode() == 2005)  //no results found.
    {
      templateData = new Array();
      templateData[0] = new Array();
      var source = document.getTemplate(this.currentQuery.templates.invalidTemplate);
      this.resultTarget.innerHTML = source.run(templateData);
      this.resultTarget.scrollTop = 0;
    }
  }
  else
  {
    if (typeof requestType == "object")
    {
      var requestInfo = requestType;
      requestType = requestType.request;
    }
    switch (requestType)
    {
      case 'GIS.Zoom.to.queryResults':
        var data = clientReply.getObject();
        if (document.mapObject.measureControl != null)
           document.mapObject.measureControl.distanceReset();
        document.mapObject.extent = data.zoomExtent;
        document.mapObject.mapImage.imageNode.src = document.mapObject.correctURL(data.mapImages[0][1]);
        if (document.mapObject.vmapPresent)
          document.mapObject.vmapImage.imageNode.src = document.mapObject.correctURL(data.mapImages[1][1]);
        if (document.mapObject.legendVisible)
          document.mapObject.loadLegend();
        document.mapObject.setWaiting(false);
        this.addZoomToMarkupToIndex(requestInfo.themeID,data);
        break;
      case 'SQL.storedDefinedQuery.save':
        noResults = true;
        if (this.savedQueryIndexPanel)
          this.savedQueryIndexPanel.getList();
        break;
      case 'SQL.export.execute':
        noResults = true;
        var url = clientReply.getObject();
        downloadFile(url); 
        document.mapObject.setWaiting(false);
        break;
      default:
        var sqlData = clientReply.getObject();
        if ((sqlData == null) || (sqlData != false))
        {
          this.currentResultData = cloneObject(sqlData);
          var source = document.getTemplate(this.currentQuery.templates.validTemplate);
          try{
            this.resultTarget.innerHTML = source.run(sqlData);
          }
          catch(e)
          {
            this.resultTarget.innerHTML = '';
          }
          
          //add fixed-position header
          var tables = this.resultTarget.getElementsByTagName('TABLE');
          if ((tables.length>0)&&(!xOp7Up))
          {
            var header = new ScrollableTable(tables[0],this.resultTarget,-2);
          }
          
          this.resultTarget.scrollTop = 0;
          try{
            var tags = cssQuery('[title]',this.resultTarget.getElementsByTagName('TH')[0]);
            for(var idx in tags)
              tags[idx].title = tags[idx].title;
          }
          catch(e){
            dprintf(this.id+'.callback: CSS query threw an exception:');
            dprintf(describeObject('e',e));
          }
          this.resultTarget.query = this;
        }
    }
  }
  if (this.onQueryReturn&&(!noResults))
    this.onQueryReturn();
};

QueryControl.prototype.redrawTemplate = function()
{
  if (this.resultTarget.scrollHandler!=null)
    this.resultTarget.scrollHandler.cleanup();

  if(this.currentResultData != null)
  {
    this.currentQuery = this.config[this.currentQueryId];
    if (this.currentQuery != null)
    {
      var source = document.getTemplate(this.currentQuery.templates.validTemplate);
      try{ 
        this.resultTarget.innerHTML = source.run(this.currentResultData);
        var tables = this.resultTarget.getElementsByTagName('TABLE');
        if ((tables.length>0)&&(!xOp7Up))
        {
          var header = new ScrollableTable(tables[0],this.resultTarget,-2);
        }
        
      }
      catch(e)
      {
        this.resultTarget.innerHTML = '';
      }
      this.resultTarget.scrollTop = 0;
      var tags = cssQuery('[title]',this.resultTarget.getElementsByTagName('TH')[0]);
      for(var idx in tags)
        tags[idx].title = tags[idx].title;
      this.resultTarget.query = this;
    }
    else
      alert('Unable to display result template for query '+this.currentQueryId+'.\nThe query configuration could not be found.');
  }
  else
    alert('Unable to display result template for query '+this.currentQueryId+'.\nNo result data is present.');
};

