document.queryControl = new(function (newId)
{
  OBJECT_MANAGER.addControl(this,'queryControl', newId);
  this.id = newId;
  this.config = null;
  this.resultTarget = null;
  this.currentQueryPage = 0;
  this.currentQueryId = null;
  this.currentQueryValuePairs = null;
  this.numQueries = 0;
  this.zoomToMarkupHandle = null;

this.setConfig = function(newConfig)
{
  //sets the configration to the specified data structre.
  this.config  = newConfig;
  for (var currentQuery in this.config)
  {
    if(currentQuery=='toJSONString')continue;
    this.numQueries++;
    document.registeredSearches[document.registeredSearches.length] = 'customQuery['+currentQuery+']';
  }
};

this.initialize = function()
{
  //generate html strings
  //set element contents
  //assign element event handlers
  //make sure all forms are hidden by default
};

this.setFormPanel = function (newFormPanel)
{
  //set the form panel reference and do initial population
  this.formPanel = newFormPanel;
};

this.formTitleEventListener = function(e)
{
  var evt = new xEvent(e);
  while((evt.target != null) && (evt.target.nodeName == '#text'))
    evt.target = evt.target.parentNode;
  if (evt.target == null)
    return;
  var currentQuery = evt.target.queryId;
  switch (evt.type)
  {
    case 'mouseover':
      setClass(evt.target,'searchFormTitleHighlight');
      break;
    case 'mouseout':
      setClass(evt.target,((document.activeSearch=='customQuery['+currentQuery+']')?('searchFormTitleActive'):('searchFormTitle')));
      break;
    case 'click':
      toggleSearchForm('customQuery['+currentQuery+']');
      break;
  }
};

this.drawFormPanel = function()
{
  for (var currentQuery in this.config)
  {
    if(currentQuery=='toJSONString')continue;
    var titleContainer = document.createElement('DIV');
    var formContainer = document.createElement('DIV');
    titleContainer.id = 'customQuery['+currentQuery+']TitleContainer';
    formContainer.id = 'customQuery['+currentQuery+']Form';
    formContainer.style.display = 'none';
    this.formPanel.appendChild(titleContainer);
    this.formPanel.appendChild(formContainer);
    var titleElement = document.createElement('SPAN');
    titleElement.id = 'customQuery['+currentQuery+']Title';
    titleContainer.appendChild(titleElement);
    titleElement.queryId = currentQuery;
    setClass(titleElement,'searchFormTitle');
    xAddEventListener(titleElement,'mouseover',this.formTitleEventListener,false);
    xAddEventListener(titleElement,'mouseout',this.formTitleEventListener,false);
    xAddEventListener(titleElement,'click',this.formTitleEventListener,false);
    titleElement.innerHTML = this.config[currentQuery]['title'];
    formContainer.innerHTML =   '<div class="leftColumnFormBorder"><div>'+
      this.config[currentQuery]['HTMLForm']+
      '</div><div class="leftColumnFormButton">'+
      '<input type="submit" class="submitButton" value="Go" onclick="return submitCustomQuery(\''+currentQuery+'\');">'+
      '</div>'+
      '</div>';
    var inputElements = formContainer.getElementsByTagName('input');
    for (var elementIndex=0;elementIndex<inputElements.length;elementIndex++)
    {
      inputElements[elementIndex].queryId = currentQuery;
      inputElements[elementIndex].queryControl = this;
      xAddEventListener(inputElements[elementIndex],'keypress',function(e){evt = new xEvent(e);if (evt.keyCode==13){submitCustomQuery(evt.target.queryId);}});
    }
    
    if (this.config[currentQuery].suggestConfig!=null)
    {
      for (var currentSuggestIndex = 0; currentSuggestIndex < this.config[currentQuery].suggestConfig.length; currentSuggestIndex++)
      {
        document.SuggestControl.addSuggest(this.config[currentQuery].suggestConfig[currentSuggestIndex]);
      }
    }
  };

  //set up any dynamic selection fields
  for(var i=0;i<this.config[currentQuery]["fieldList"].length;i++){
    if(this.config[currentQuery]["fieldList"][i].fieldType=='dynamicselectField'){
      this.buildDynamicSelect(currentQuery,i);
    }
  };
  
  return;
};

this.buildDynamicSelect=function(queryid,fieldid){
  var fieldName = this.config[queryid]["fieldList"][fieldid]["fieldName"],
   config=this.config[queryid]["fieldList"][fieldid]["dynamicList"],
   container=$('sqlQuery.'+queryid+'.'+fieldName+'InputContainer');
  if(container){
    container.innerHTML='Loading...';
    var htmstr=['<select id="sqlQuery.'+queryid+'.'+fieldName+'InputField">'],
    dbid=config['dbid'],table=config['table'],
    valuefield=config['valuefield'], labelfield=config['labelfield'],
    fields=labelfield+','+valuefield, where=config['whereclause'], limit=config['limit'];
    freeance_request(function(resp){
      if(resp.XMLRPC_FAULT){
        htmstr.push('<option value=""></option>');  
      }
      else
      {
        var data=resp['data'];
        for (var i=0;i<data.length;i++){
          var opt=data[i];
          htmstr.push('<option value="',opt[valuefield],'">',opt[labelfield],'</option>');
        };
      };
      htmstr.push('</select>');
      container.innerHTML=htmstr.join('');
    },'SQL.query.limitselect',dbid,[labelfield,valuefield].join(','),table,where,limit,0);
  }
};

this.setResultTarget = function (newResultTarget)
{
  //set a reference to the target element for query results.
  this.resultTarget = newResultTarget;
};

this.getFormValues = function (newQueryId)
{
  var queryValuePairs = [];
  var fieldList = this.config[newQueryId]['fieldList'];
  for (var i=0;i<fieldList.length;i++)
  {
    var fieldName = fieldList[i]['fieldName'];
    var inputElement = $('sqlQuery.'+newQueryId+'.'+fieldName+'InputField');
    if(inputElement)
      queryValuePairs.push([fieldName,inputElement.value.strtrim()?inputElement.value.strtrim():fieldList[i]['defaultValue']]);
    else
      queryValuePairs.push([fieldName,fieldList[i]['defaultValue']]);
  }
  return queryValuePairs;
};

this.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);
};


this.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)
  {
    if(currentValue=='toJSONString')continue;
    this.currentQueryValuePairs[valueIndex] = new Array(newValuePairs[currentValue][0],newValuePairs[currentValue][1]);
    valueIndex++;
  }
  var requestInfo = new Object;
  requestInfo.request = 'runQuery';
  requestInfo.queryId = queryId;
  requestInfo.queryTitle = this.currentQuery.title;
  document.getElementById('textResultTabContainer').innerHTML = '';
  if (this.loadImage != null)
    document.getWidgetById(this.loadImage).show();
  if (this.onQuerySubmit)
    this.onQuerySubmit();
  document.mapObject.redraw();
  if (this.zoomToMarkupHandle != null)
  {
    makeSyncPostRequest(XMLRPC_URL,'GIS.DrawPlane.remove.Shape',document.mapObject.sessionID,0,this.zoomToThemeId,this.zoomToMarkupHandle, document.mapObject.mapImage.width(),document.mapObject.mapImage.height());
    document.mapObject.redraw();
    this.zoomToMarkupHandle = null;
  }
  
  var data = makeASyncPostRequest(this,this.currentQuery,XMLRPC_URL,this.currentQuery.request.requestMethod,this.currentQuery.request.pdqIdentifier,this.currentQuery.templates.pageRows,this.currentQueryPage,this.currentQueryValuePairs);
};

this.loadNextPage = function()
{
  this.runQuery(this.currentQueryId,this.currentSourceValuePairs,this.currentQueryPage+1, false);
};

this.loadPreviousPage = function()
{
  this.runQuery(this.currentQueryId,this.currentSourceValuePairs,this.currentQueryPage-1, false);
};

this.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 (realData.length == 0)
  {
    if (this.loadImage != null)
      document.getWidgetById(this.loadImage).show();
    if (realData.length == 0)
      alert('No data to zoom to.');
    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
  this.zoomToThemeId = themeId;
  document.mapObject.setWaiting(true);
  if (this.zoomToMarkupHandle != null)
  {
    makeSyncPostRequest(XMLRPC_URL,'GIS.DrawPlane.remove.Shape',document.mapObject.sessionID,0,themeId,this.zoomToMarkupHandle, document.mapObject.mapImage.width(),document.mapObject.mapImage.height());
    this.map.redraw();
    this.zoomToMarkupHandle = null;
  }
  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);
};

this.callback = function(serverReplyDoc, requestInfo)
{
  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('clientReply fault:\n\n'+clientReply.getFaultCode()+'\n'+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);
      document.getElementById('textResultTabContainer').innerHTML = 'No Results Found';
    }
  }
  else
  {
    if (typeof requestInfo == "object")
      requestType = requestInfo.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.mapImages[0][2];
        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();
        this.zoomToMarkupHandle = data.handle;
        document.mapObject.setWaiting(false);
        break;
      case 'SQL.export.execute':
        var url = clientReply.getObject();
        downloadFile(url);
        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 = '';
          }
          var tags = cssQuery('[title]',this.resultTarget.getElementsByTagName('TH')[0]);
          for(var idx in tags){
            if(idx=='toJSONString')continue;
            tags[idx].title = document.babelfish.translateWord(tags[idx].title);
          }
          this.resultTarget.query = this;
          var usePlural = (sqlData.length!=1);
          document.getElementById('textResultTabContainer').innerHTML = sqlData[3].length+' Result'+(usePlural?'s':'')+' Found '+((sqlData[1]>1)?('(Page '+sqlData[0]+' of '+sqlData[1]+')'):(''));
          scrollToSearchResultsRange();
        }
    }
  }
  if (this.onQueryReturn)
    this.onQueryReturn();
};

this.clearResults = function()
{
  if (this.resultTarget)
  {
    document.getElementById('textResultTabContainer').innerHTML = '';
    this.resultTarget.style.display = 'none';
    this.resultTarget.innerHTML = '';  // faster to clear after hiding, omits a rendering op
  }
  if (this.zoomToMarkupHandle != null)
  {
    makeSyncPostRequest(XMLRPC_URL,'GIS.DrawPlane.remove.Shape',document.mapObject.sessionID,0,this.zoomToThemeId,this.zoomToMarkupHandle, document.mapObject.mapImage.width(),document.mapObject.mapImage.height());
    document.mapObject.redraw();
    this.zoomToMarkupHandle = null;
  }
};

})('queryControl');
