/**********************************************************************
 *
 * expat_resultset.cpp --
 *
 * Copyright (C) 2005-2010  The 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 <stdio.h>
#include <string.h>
#include <expat.h>

#if defined(GSDL_USE_OBJECTSPACE)
#  include <ospace\std\iostream>
#elif defined(GSDL_USE_IOS_H)
#  include <iostream.h>
#else
#  include <iostream>
using namespace std;
#endif

#include "text_t.h"
#include "queryinfo.h"
#include "gsdlunicode.h"

struct queryresultpack {
  queryresultsclass* queryresult_ptr;
  int match_count;
};

char* get_attribute(const char** attr, char* att_name)
{
  char* att_val = NULL;

  for (int i = 0; attr[i]; i += 2) {
    if (strcmp(attr[i],att_name)==0) {
      att_val = strdup(attr[i+1]);
    }
  }

  return att_val;
}

static void XMLCALL 
startElement(void *userData, const char *name, const char **attributes)
{
  queryresultpack* qrpack_ptr = (queryresultpack*)userData;
  queryresultsclass* queryresult_ptr = qrpack_ptr->queryresult_ptr;

  text_t element_name = (char*)name;

  // if (element_name == "ResultSet") {
  //   char* cached_attribute_str = get_attribute(attributes, "cached");
  //   if (cached_attribute_str != NULL) {
  //     cerr << "Cached: " << cached_attribute_str << endl;
  //   }
  // }

  if (element_name == "Error") {
    char* error_type_str = get_attribute(attributes, "type");
    queryresult_ptr->error_message = error_type_str;
    if ((text_t) error_type_str == "PARSE_EXCEPTION") {
      queryresult_ptr->syntax_error = true;
    }
  }

  if (element_name == "Term") {
    char* term_value_str = get_attribute(attributes, "value");
    char* term_frequency_str = get_attribute(attributes, "freq");

    termfreqclass termfreqobj;
    termfreqobj.termstr = to_uni(term_value_str);

    termfreqobj.termfreq = atoi(term_frequency_str);
    queryresult_ptr->orgterms.push_back(termfreqobj);
  }

  if (element_name == "StopWord") {
    char* stop_word_value_str = get_attribute(attributes, "value");
    queryresult_ptr->stopwords.insert((text_t) stop_word_value_str);
  }

  if (element_name=="MatchingDocsInfo") {
    char* num_match_docs_str = get_attribute(attributes,"num");
    if (num_match_docs_str != NULL) {
      int num_match_docs = atoi(num_match_docs_str);

      queryresult_ptr->docs_matched = num_match_docs;
      free(num_match_docs_str);
    }
    else {
      queryresult_ptr->docs_matched = 0;
    }
  }


  if (element_name=="Match") {

    char* id = get_attribute(attributes,"id");
    if (id != NULL)
    {
      docresultclass doc;
      doc.clear();
      doc.docid = id;

      char* docrank = get_attribute(attributes, "rank");
      if (docrank != NULL)
      {
	doc.docweight = atof(docrank);
      }

      char* termfreq = get_attribute(attributes, "termfreq");
      if (termfreq != NULL)
      {
	doc.num_query_terms_matched = atoi(termfreq);
      }

      queryresult_ptr->docs.docset[doc.docid] = doc;
      queryresult_ptr->docs.docorder.push_back(doc.docid);
      ++qrpack_ptr->match_count;

      free(id);
    }
    
  }
}

static void XMLCALL
endElement(void *userData, const char *name)
{
  // no need to do anything
}




int expat_resultset(text_t& xml_text, queryresultsclass& queryresult)
{
  queryresult.clear();
  queryresultpack qrpack = { &queryresult, 0 };

  char * xml_text_cstr = xml_text.getcstr();
  
  XML_Parser parser = XML_ParserCreate(NULL);
  
  XML_SetUserData(parser, &qrpack);
  XML_SetElementHandler(parser, startElement, endElement);
  
  int return_status = 0;
  const int parse_status 
    = XML_Parse(parser, xml_text_cstr, strlen(xml_text_cstr), XML_TRUE);
  
  if (parse_status == XML_STATUS_ERROR) {
    fprintf(stderr,
	    "%s at line %d\n",
	    XML_ErrorString(XML_GetErrorCode(parser)),
	    XML_GetCurrentLineNumber(parser));
    return_status = 1;
  }
  
  XML_ParserFree(parser);
  delete []xml_text_cstr;
  
  return return_status;
}
