/**********************************************************************
 *
 * sqlqueryfilter.cpp -- 
 * Copyright (C) 2010  New Zealand Digital Library Project
 *
 * A component of the Greenstone digital library software
 * from the New Zealand Digital Library Project at the
 * University of Waikato, New Zealand.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 *********************************************************************/

#include "sqlqueryfilter.h"

sqlqueryfilterclass::sqlqueryfilterclass ()
  : sqlfilterclass()
{
  FilterOption_t filtopt;

  // -- onePerQuery StartResults   integer
  filtopt.clear();
  filtopt.name = "StartResults";
  filtopt.type = FilterOption_t::integert;
  filtopt.repeatable = FilterOption_t::onePerQuery;
  filtopt.defaultValue = "1";
  filtopt.validValues.push_back("1");
  filtopt.validValues.push_back("1000");
  filterOptions["StartResults"] = filtopt;

  // -- onePerQuery EndResults     integer
  filtopt.clear();
  filtopt.name = "EndResults";
  filtopt.type = FilterOption_t::integert;
  filtopt.repeatable = FilterOption_t::onePerQuery;
  filtopt.defaultValue = "10";
  filtopt.validValues.push_back("-1");
  filtopt.validValues.push_back("1000");
  filterOptions["EndResults"] = filtopt;

  // -- onePerQuery  Maxdocs  integer
  filtopt.clear();
  filtopt.name = "Maxdocs";
  filtopt.type = FilterOption_t::integert;
  filtopt.repeatable = FilterOption_t::onePerQuery;
  filtopt.defaultValue = "200";
  filtopt.validValues.push_back("-1");
  filtopt.validValues.push_back("1000");
  filterOptions["Maxdocs"] = filtopt;

  // --  IndexFieldDomain, enumerated, used to list available fields (from)
  filtopt.clear();
  filtopt.name = "IndexFieldDomain";
  filtopt.type = FilterOption_t::enumeratedt;
  filtopt.repeatable = FilterOption_t::onePerTerm;
  filtopt.defaultValue = "";
  filterOptions["IndexFieldDomain"] = filtopt;

  // --  IndexFieldRange, enumerated, used to list available fields (to)
  //     Equivalent to IndexField in full text search filter
  filtopt.clear();
  filtopt.name = "IndexFieldRange";
  filtopt.type = FilterOption_t::enumeratedt;
  filtopt.repeatable = FilterOption_t::onePerTerm;
  filtopt.defaultValue = "";
  filterOptions["IndexFieldRange"] = filtopt;

}


sqlqueryfilterclass::~sqlqueryfilterclass ()
{}




void sqlqueryfilterclass::configure (const text_t &key, 
				     const text_tarray &cfgline) 
{
  sqlfilterclass::configure(key, cfgline);
  
  if (key == "indexfieldmap") {
    indexfieldmap.importmap (cfgline);
    
    // update the list of indexes in the filter information
    text_tarray from_options;
    indexfieldmap.getfromarray (from_options);
    filterOptions["IndexFieldDomain"].validValues = from_options;

    text_tarray to_options;
    indexfieldmap.gettoarray (to_options);
    filterOptions["IndexFieldRange"].validValues = to_options;

  } else if (key == "defaultindex") { 

    filterOptions["IndexFieldDomain"].defaultValue = cfgline[0];

    indexfieldmap.from2to (cfgline[0], 
			   filterOptions["IndexFieldRange"].defaultValue);
  }
}

bool sqlqueryfilterclass::init (ostream &logout) 
{
  if (!sqlfilterclass::init(logout)) {
    return false;
  }
  
  if (filterOptions["IndexFieldRange"].defaultValue.empty()) {
    // use first index in map as default if no default is set explicitly

    text_tarray fromarray;
    indexfieldmap.getfromarray(fromarray);

    text_tarray toarray;
    indexfieldmap.gettoarray(fromarray);

    if (fromarray.size()) {
      filterOptions["IndexFieldDomain"].defaultValue = fromarray[0];
    }

    if (toarray.size()) {
      filterOptions["IndexFieldRange"].defaultValue = toarray[0];
    }
  }

  return true;
}

void sqlqueryfilterclass::filter (const FilterRequest_t &request,
				  FilterResponse_t &response,
				  comerror_t &err, ostream &logout)
{
  outconvertclass text_t2ascii;

  if (!connect_to_sqldb(response,err,logout)) {
    return;
  }
  
  text_t sql_where = "";
  text_t sort_by_metadata_element_name = "";
  OptionValue_tarray::const_iterator options_iterator = request.filterOptions.begin();
  while (options_iterator != request.filterOptions.end())
    {
      if ((*options_iterator).name == "SQLWhere") {
	sql_where = (*options_iterator).value;
      }
      if ((*options_iterator).name == "SortField") {
	sort_by_metadata_element_name = (*options_iterator).value;
      }
      options_iterator++;
    }

  text_tarray document_OIDs = sql_db_ptr->get_documents_where (sql_where, sort_by_metadata_element_name);
  int numDocs = document_OIDs.size();

  // Fill in response.docInfo with the document OIDs
  text_tarray::iterator document_OID_iterator = document_OIDs.begin();
  while (document_OID_iterator != document_OIDs.end())
    {
      ResultDocInfo_t document_result_doc;
      document_result_doc.OID = *document_OID_iterator;
      response.docInfo.push_back (document_result_doc);

      document_OID_iterator++;
    }

  disconnect_from_sqldb();

  response.numDocs = numDocs;
  response.isApprox = Exact;

}
