/**************************************************************************
 *
 * MGQuery.h -- Query related functions
 * Copyright (C) 1999  Rodger McNab
 *
 * 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.
 *
 **************************************************************************/

#ifndef MGQUERY_H
#define MGQUERY_H

#include "IndexData.h"
#include <limits.h>
#include "Terms.h"

// forms base for defining and calculating the boolean
// part of a query
class QueryNode {
public:
  QueryNode ();
  virtual ~QueryNode ();

  virtual void Calculate (IndexData &indexData, const QueryInfo &queryInfo,
			  QueryResult &result) const;
  virtual void Free ();
  virtual void Print (ostream &s, int indent=0) const;
};



void PrintIndent (ostream &s, int indent);
void PrintIndentText (ostream &s, char *text, int indent);
void PrintNode (ostream &s, QueryNode *node, int indent=0);



// basic boolean nodes

class AndQueryNode : public QueryNode {
public:
  QueryNode *leftNode;
  QueryNode *rightNode;
  
  AndQueryNode ();
  ~AndQueryNode ();

  void Calculate (IndexData &indexData, const QueryInfo &queryInfo,
		  QueryResult &result) const;
  void Free ();
  void Print (ostream &s, int indent=0) const;
};

class OrQueryNode : public QueryNode {
public:
  QueryNode *leftNode;
  QueryNode *rightNode;
  
  OrQueryNode ();
  ~OrQueryNode ();

  void Calculate (IndexData &indexData, const QueryInfo &queryInfo,
		  QueryResult &result) const;
  void Free ();
  void Print (ostream &s, int indent=0) const;
};

class NotQueryNode : public QueryNode {
public:
  QueryNode *queryNode;
  QueryNode *notNode;
  
  NotQueryNode ();
  ~NotQueryNode ();

  void Calculate (IndexData &indexData, const QueryInfo &queryInfo,
		  QueryResult &result) const;
  void Free ();
  void Print (ostream &s, int indent=0) const;
};



class TagNode {
public:
  UCArray tagName;

  void Clear ();
  TagNode () { Clear (); }

  void Calculate (IndexData &indexData, FragRangeArray &fragRange) const;
  void Free ();
  void Print (ostream &s, int indent=0) const;
};


#define NO_TERM_RANGE_START (INT_MIN/2)
#define NO_TERM_RANGE_END   (INT_MAX/2)

/* NOTE: range stuff - the range values are for the previous term relative
to the current term. So if searching for the phrase "the cat", 'the' doesn't 
need range limits, but 'cat' has a range of -2 to -1. ie, if have found 'cat'
then 'the' has to be at position between -2 and -1 relative to 'cat'.
"the cat" could also be searched for by 'cat' with no range limits, then 'the' with range 0 to 1.
range values are relative to the gaps between words:
   x   y   z   X   a   b   c
    -3   -2  -1  0   1   2   3

 */
class TermNode {
public:
  UCArray term;
  mg_u_long termWeight;
  mg_u_long stemMethod;
  mg_s_long startRange; // range relative to last term
  mg_s_long endRange;
  
  void Clear ();
  TermNode ();

  // fragLimits can be NULL if not neede
  void Calculate (IndexData &indexData,
		  bool needFragFreqs,
		  FragRangeArray *fragLimits,
		  FragData &fragData,
		  UCArrayVector &equivTerms) const;
  void Free ();
  void Print (ostream &s, int indent=0) const;
};

typedef vector<TermNode> TermNodeArray;


class ProxMatchQueryNode : public QueryNode {
public:
  TagNode *tagNodePtr; // optional field
  TermNodeArray terms;
  
  ProxMatchQueryNode ();
  ~ProxMatchQueryNode ();

  void Calculate (IndexData &indexData, const QueryInfo &queryInfo,
		  QueryResult &result) const;
  void Free ();
  void Print (ostream &s, int indent=0) const;
};

class BrowseQueryNode :public QueryNode {
 public:
  UCArray term;
  mg_s_long startPosition;
  mg_u_long numTerms;

  void Clear();
  BrowseQueryNode () { Clear(); }
  //  ~BrowseQueryNode ();

  void Calculate (IndexData &indexData, BrowseQueryResult &result) const;
  void Free ();
  void Print (ostream &s, int indent=0) const;




};

void MGQuery (IndexData &indexData,
	      const QueryInfo &queryInfo,
	      const QueryNode *queryTree,
	      QueryResult &result);

// this function for retrieving results with both section doc nums
// and Document docnums
void MGQuery (IndexData &indexData,
	      const QueryInfo &queryInfo,
	      const QueryNode *queryTree,
	      ExtQueryResult &result, UCArray &level);


// new function for full text browsing, 
void MGBrowseQuery (IndexData &indexData, UCArray &level,
		  const BrowseQueryNode &node,
		  BrowseQueryResult &result);

#endif
