#ifndef __Query_h__
#define __Query_h__

//
// for details see the book:
// Design Patterns, by the infamous GoF
// page 243, Interpreter pattern
// Don't have this masterpiece? Buy it *now*.
//

#include "Object.h"
#include "htString.h"
#include "List.h"
#include "Dictionary.h"

class ResultList;

//
// a parsed, executable query
// abstract class
//
class Query : public Object
{
public:
	virtual ~Query();
	virtual ResultList *Evaluate() = 0;
	virtual void Add(Query *) {};
	virtual String GetLogicalWords() const = 0;

protected:
	Query() {}
	static const ResultList *ignore;
};

//
// a query that looks up for an exact word
//
class ExactWordQuery : public Query
{
public:
	ExactWordQuery(const String &word);
	~ExactWordQuery();

	ResultList *Evaluate();

	static ExactWordQuery *Lookup(const String &word);

	String GetLogicalWords() const;

private:
	ResultList *result;
	String word;
	static Dictionary cache;
};

//
// a query that looks up for a word
// applying fuzzy methods to it.
// Eventually may go search results in the
// ExactWord cache
//
class FuzzyWordQuery : public Query
{
public:
	FuzzyWordQuery(const String &word);
	~FuzzyWordQuery();

	ResultList *Evaluate();

	String GetLogicalWords() const;

	static void AddFuzzyMethod(Query *filter);

private:
	String word;
	ResultList *result;
	static List filters;
	static Dictionary cache;
};

//
// operator query
// abstract class
// a query that combines and scores the result lists
// returned by other queries
//
class OperatorQuery : public Query
{
public:
	virtual ~OperatorQuery()
	{
		operands.Destroy();
	}

	void Add(Query *operand)
	{
		operands.Add(operand);
	}

	virtual ResultList *Evaluate() = 0;
	String GetLogicalWords() const;

protected:
	OperatorQuery() {}

	virtual String OperatorString() const = 0;

	List operands; // List<Query *>
};

//
// and query
// an operator query that does 'and' combination
// 
class AndQuery : public OperatorQuery
{
public:
	ResultList *Evaluate();

private:
	ResultList *Intersection();
	String OperatorString() const { return String("and"); }
};

//
// and query
// an operator query that does 'or' combination
//
class OrQuery : public OperatorQuery
{
public:
	ResultList *Evaluate();

private:
	ResultList *Union();
	String OperatorString() const { return String("or"); }
};

//
// not operator (n-ary not!)
// not(a, b, c, d...) == a except (b or c or d or...)
//
class NotQuery : public OperatorQuery
{
public:
	ResultList *Evaluate();

private:
	ResultList *Substract();
	String OperatorString() const { return String("not"); }
};

//
// near query
// an operator that performs combination by match proximity
//
class NearQuery : public OperatorQuery
{
public:
	NearQuery(Query *left, Query *right, size_t dist) :
		distance(dist)
		{ Add(left); Add(right); }

	ResultList *Evaluate();

private:
	ResultList *Near();
	String OperatorString() const;
	size_t distance;
};

//
// next query
// an operator used for phrase construction
//
class NextQuery : public OperatorQuery
{
public:
	NextQuery(Query *left, Query *right)
		{ Add(left); Add(right); }

	ResultList *Evaluate();

private:
	ResultList *Next();
	String OperatorString() const { return String("next-to"); }
};

#endif
