// Change History
// 11/12/03 AV Production: Add getIndexType
// 10/28/03 AV Production: 64 bit conversion

//
// AT_INDEX.H -- High-Level Index-Retrieval Classes
//
// To do a search :
//   1. Decide which AT_Index_List contains your index.
//   2. Open (construct) the AT_Index_List.
//   3. Open proper AT_Index with openIndex.
//   4. Get record list with AT_Index::search
//
// To browse an index :
//   1. Get iterator for index.
//   2. Get AT_Index_Term from iterator with operator*.
//   3. Get term from AT_Index_Term.
//

#ifndef AT_INDEX_H
#define AT_INDEX_H

#include "at_defs.h"
#include "x_at_file.h"

#include "at_objects.h"

#include "at_error.h"
#include "at_reporterr.h"

namespace Xpace
{
  class Index;
  class Index_Iter;
  class IndexList;
}

// ================================== INDEX ===================

enum { MAX_TERM_LEN = 255 };

// search result
class SEARCH_DECL AT_Record_List;

//Charachter set
class SEARCH_DECL AT_Charset;

class SEARCH_DECL AT_Index
{
public :
  AT_Index
    (int = 0);

  AT_Index
    (AT_Read_Rand_File *indexFile,
     uint8 indexType,
     uint64 indexOffset,
     uint32 indexSize,
     uint32 headerSize,
     uint   featureBits,
     uint32 dbRecords);

  static AT_Index AT_Index::null;
  // (in)valid?
  virtual bool operator!
    ()
    const;

  virtual ~AT_Index
    ();

  // cloning
  virtual AT_Index *clone
    ()
    const
    { return new AT_Index(*this); };

  virtual AT_Index* sort
    ()
    const
    { return clone(); }

  uint getRecordCount
    ()
    const;

  // is index numeric?
  virtual bool isNumeric
    ()
    const;

  // terms in index
  // AXV made it virtual so quantile index can override.
  virtual uint32 getTermCount
    ()
    const;

  // does index include term record counts?
  bool hasCounts
    ()
    const;

  // charachter set
  const AT_Charset *getCharset
    ()
    const;

  // term search; redefine to change terms (e.g. for vectors)
  virtual AT_Record_List search
    (AT_Num term)
    const;
  virtual AT_Record_List search
    (AT_String term)
    const;

  // range search
  virtual AT_Record_List search
    (AT_Num start,
     AT_Num end)
    const;
  virtual AT_Record_List search
    (AT_String start,
     bool startIncl,
     AT_String end = 0,
     bool endIncl = true)
    const;

  // optimized "all" and "none" searches
  virtual AT_Record_List searchAll
    ()
    const;
  virtual AT_Record_List searchNone
    ()
    const;

  // redefine to change terms (e.g. for vectors)
  virtual AT_Num browseTerm
    (AT_Num term)
    const
  { return term; };
  virtual byte* browseTerm
    (byte *term,
     uint *termLen)
    const
  { return term; };

  #ifndef NDEBUG
  bool test
    (AT_Num term,
     uint32 recNum)
    const;
  bool test
    (AT_String term,
     uint32 recNum)
    const;
  #endif

  // iterator access to terms (e.g. browse)
  class SEARCH_DECL Iter;
  virtual Iter begin
    (AT_Num term)
    const;
  virtual Iter begin
    (AT_String term = 0)
    const;
  virtual Iter end
    ()
    const;

  uint8 getIndexType
    ()
    const;
  // direct index access; see also terms.h
  class directAccess
  {
  public :
    virtual bool rec
      (uint32 recNum)
    = 0;
    virtual bool term
      (const Iter& it)
    = 0;
    virtual bool status
      (uint32 currentTerm,
       uint32 totalTerms)
      const
    { return true; };
    virtual bool isReadRecList
      ()
      const
    { return true; }
  };
  static bool forEachRecord
    (Iter& begin,
     Iter& end,
     directAccess *called);

  static bool forEachRecordInFile
    (Iter& begin,
     Iter& end,
     directAccess *called,
     AT_Read_Rand_File *f);

  static bool forEachTerm
    (Iter& begin,
     Iter& end,
     directAccess *called);

  class SEARCH_DECL Impl;
  const Xpace::Index* x_Index;
  AT_Index
    (const Xpace::Index* x) :
      x_Index(x)
  {}
  AT_Index
    (const AT_Index& rhs);
  AT_Index& operator=
    (const AT_Index& rhs);

private :
  uint db_records;
};

// ================================== INDEX (TERM) ITERATOR ===

// get this from index iterator; access to index terms (e.g. browse)
class SEARCH_DECL AT_Index_Term;

class SEARCH_DECL AT_Index::Iter 
{
  friend AT_Index;

public :
  Iter
    (const AT_Index *index);

  Iter
    (const Iter&);
  Iter& operator=
    (const Iter&);

  ~Iter
    ();

  bool operator!
    ()
    const;

  // how many terms?
  uint32 getRange
    ()
    const;

  bool operator==
    (const Iter& rhs)
    const;
  bool operator!=
    (const Iter& rhs)
    const;

  AT_Index_Term operator*
    ()
    const;

  Iter& operator++
    ();
  Iter operator++
    (int);

  Iter& operator--
    ();
  Iter operator--
    (int);

  Iter& operator+=
    (int32 n);
  Iter operator+
    (int32 n)
    const;
  Iter& operator-=
    (int32 n);
  Iter operator-
    (int32 n)
    const;

  int32 operator-
    (const Iter& rhs)
    const;

  const AT_Index_Term operator[]
    (uint32 n)
    const;

  bool operator<
    (const Iter &rhs)
    const;
  bool operator>
    (const Iter &rhs)
    const;
  bool operator<=
    (const Iter &rhs)
    const;
  bool operator>=
    (const Iter &rhs)
    const;

  static AT_Index::Iter null;

  const Xpace::Index* x_Index;
  Xpace::Index_Iter* x_Iter;
  const uint db_records;
  Iter
    (const Xpace::Index* xIndex = 0,
     Xpace::Index_Iter* xIter = 0,
     const uint dbRecords = 0) :
      x_Index(xIndex),
      x_Iter(xIter),
      db_records(dbRecords)
  {};
};

// access to index term info; get this from index iterator
class SEARCH_DECL AT_Index_Term
{
public :
  AT_Index_Term
    ();

  // (in)valid term?
  bool operator!
    ()
    const;

  // terms equal
  bool operator==
    (const AT_Index_Term& rhs)
    const;

  // get term; return term if numeric
  AT_Num getTerm
    (byte *buf = 0,
     uint buflen = 0)
    const;

  // get count of records with this term
  uint32 getRecordCount
    ()
    const;

  static AT_Index_Term null;

  AT_Index_Term
    (bool numeric,
     const byte* term,
     uint len);
  std::vector<byte> term;
  int64 val;
};


// ============================================================
// ================================== INDEX LIST ==============


// list of indexes
// AT_Indexes are available from an AT_Index_List by index number.
// Index numbers are the client's responsibility.

class SEARCH_DECL AT_Index_List
{
public :
  AT_Index_List
    (AT_Read_Rand_File *indexRefs,
     AT_Read_Rand_File *indexes);

  AT_Index_List
    (AT_String indexRefName,
     AT_String indexName);

  AT_Index_List
    (const AT_Index_List&);
  AT_Index_List& operator=
    (const AT_Index_List&);

  bool operator!
    ()
    const;

  ~AT_Index_List
    ();

  // how many indexes?
  uint32 getNumIndexes
    ()
    const;

  // does index exists
  bool indexExists
    (uint32 indexNum)
    const;

  AT_Index openIndex
    (uint32 indexNum)
    const;

  // errors
  class Error;
  class openError;
  class noIndex;

  mutable Xpace::IndexList*  x_IndexList;
};

class SEARCH_DECL AT_Index_List::Error : public AT_Error
{
public :
  class Reporter;
  virtual void report
    (Reporter& reporter)
    const
  {};

protected :
  Error
    (const char *module = 0,
     uint lineNum = 0,
     AT_String objectType = 0,
     AT_String objectName = 0,
     const AT_Error *const prev = 0) :
    AT_Error(module, lineNum, objectType, objectName, prev)
  {};
};

class SEARCH_DECL AT_Index_List::openError : public AT_Index_List::Error
{
public :
  openError
    (const char *module = 0,
     uint lineNum = 0,
     const AT_Error *const prev = 0,
     uint indexNum = MAXUINT) :
      Error(module, lineNum, 0, 0, prev),
      index_num(indexNum)
  {};

  openError *clone
    ()
    const
  { return new openError(*this); };

  uint getIndexNum
    ()
    const
  { return index_num; };

  virtual void report
    (Reporter& reporter)
    const
  {};

private :
  const uint index_num;
};

class SEARCH_DECL AT_Index_List::noIndex : public AT_Index_List::Error
{
public :
  noIndex
    (const char *module = 0,
    uint lineNum = 0) :
      Error(module, lineNum) 
  {};

  noIndex *clone
    ()
    const
  { return new noIndex(*this); };

  virtual void report
    (Reporter& reporter)
    const
  {};
};

class SEARCH_DECL AT_Index_List::Error::Reporter : public AT_Error::Reporter
{
public :
  //default
  virtual void report
    (const AT_Error *const err)
  {};

  virtual void report
    (const AT_Index_List::noIndex *const err)
  {};

  virtual void report
    (const AT_Index_List::openError *const err)
  {};
};

// ============================================================
// ============================================================
// ============================================================



#endif
