// Change History
// 11/20/03 AV Development: BC6 conversion.
// 10/29/03 AV Production: 64 bit conversion

#ifndef _DRS_IDX_H
#define _DRS_IDX_H

#include "base/at_defs.h"
#include "xdart/x_at_index.h"
#include "retrieve/at_quantiles.h"
#include "retrieve/roundidx.h"

#include "drs/drs_setting.h"

enum DRS_IndexType { INDEXTYPE_TEXT, INDEXTYPE_INTEGER, INDEXTYPE_COUNT};

class DRS_Index;
class DRS_Database;

class DRS_IndexDef
{
  public:
  virtual ~DRS_IndexDef() {}; // AV need virtual destructor

  virtual DRS_IndexType IndexType() const = 0;
  virtual bool          IsSortable() const = 0;
  virtual bool          IsSeekable() const = 0;
  virtual bool          IsBrowsable() const = 0;

  virtual DRS_Index *   IndexOpen( DRS_Database &rDatabase, uint iIndexFileID, uint iIndex) = 0;
};

class DRS_IndexDefInteger : public DRS_IndexDef
{
  public:
  //Constructor explicit: Vector IndexDefs
  explicit DRS_IndexDefInteger( uint normal = 0, uint width = 0, uint prec = 0, bool sort = true)
    : iNormal(normal), iWidth(width), iPrecision(prec), isAllowSort( sort)
    {};
  explicit DRS_IndexDefInteger( const DRS_IndexDefInteger & rhs)
    : iNormal(rhs.iNormal), iWidth(rhs.iWidth), iPrecision(rhs.iPrecision), isAllowSort( rhs.isAllowSort)
    {};
  //Contructor from file
  DRS_IndexDefInteger( AT_String sFile, AT_String sSection, DRS_Setting Key);

  inline DRS_IndexType IndexType() const { return INDEXTYPE_INTEGER;};

  inline bool          IsSortable() const { return isAllowSort;};
  inline bool          IsBrowsable() const { return true;};
  inline bool          IsSeekable() const { return !!iWidth;}; //Only fixed width integer indexes seekable

  inline uint          Precision() const { return iPrecision; }
  inline uint          Normal() const { return iNormal; }
  
  DRS_Index *   IndexOpen( DRS_Database &rDatabase, uint iIndexFileID, uint iIndex);
    //{ return new DRS_IntegerIndex( rDatabase.IndexOpen( iIndexFileID, iIndexIDBase + iIndex), *this); };

  protected:
  uint          iNormal;     //Normalise index contents up,
                             //Normailise index search/seek down
  uint          iWidth;      //0-pad
  uint          iPrecision;  //Index Term's precision
  bool          isAllowSort;
};

class DRS_IndexDefText : public DRS_IndexDef
{
  public:
  explicit DRS_IndexDefText( AT_String sFile, AT_String sSection, DRS_Setting Key);
           DRS_IndexDefText( DRS_IndexDefText const &rCopy);
          ~DRS_IndexDefText();

  inline DRS_IndexType IndexType() const { return INDEXTYPE_TEXT;};
  inline bool          IsSortable() const { return isAllowSort;};
  inline bool          IsBrowsable() const { return true;}; //Word left = NO!
  inline bool          IsSeekable() const { return true;};

  DRS_Index *          IndexOpen( DRS_Database &rDatabase, uint iIndexFileID, uint iIndex);

  protected:
  bool          isAllowSort;
  uint          iWidth;
  bool          isCapitalize;
  byte *        sInclusions;
};

////////////////////////////////////////////////////////
// DRS_Index Classes
////////////////////////////////////////////////////////
class DRS_Index : public AT_Index
{
  protected:
  DRS_Index( const AT_Index &base);

  public:
  virtual bool            IsSeekable() const = 0;
  virtual bool            IsText() const = 0;
  virtual AT_Index::Iter  SeekTerm( byte *sSeekString) = 0;
  virtual void            TermGet( AT_Index::Iter const &rIter, byte *sDest, uint iDestLen, uint32 *pOccurrences = 0) = 0;
  virtual uint32          TermCountGet() const { return AT_Index::getTermCount();};
  virtual AT_Record_List  Search( byte *sSearchString) const;
};

class DRS_TextIndex : public DRS_Index, public DRS_IndexDefText
{
public:
  DRS_TextIndex( AT_Index base, DRS_IndexDefText const &rIndexDef);
  DRS_TextIndex(const DRS_TextIndex &rhs);

  virtual DRS_Index       *clone() const { return new DRS_TextIndex(*this); };

  inline bool         	 IsSeekable() const { return DRS_IndexDefText::IsSeekable();};
  inline bool            IsText() const { return true;};
  virtual AT_Index::Iter SeekTerm( byte *sSeekString);
  virtual void 			 TermGet( AT_Index::Iter const &rIter, byte *sDest, uint iDestLen, uint32 *pOccurrences = 0);

  AT_Record_List         Search( byte *sSearchString) const;
};
   #include <vector>

class DRS_IntegerIndex : public DRS_Index, public DRS_IndexDefInteger
{
public:
  DRS_IntegerIndex( AT_Index base, DRS_IndexDefInteger const &rIndexDef);
  DRS_IntegerIndex(const DRS_IntegerIndex &rhs);
  ~DRS_IntegerIndex();

  virtual DRS_Index       *clone() const { return new DRS_IntegerIndex(*this); };
  inline bool         	 IsSeekable() const { return DRS_IndexDefInteger::IsSeekable();};
  inline bool            IsText() const { return false;};
  virtual AT_Index::Iter SeekTerm( byte *sSeekString);
  virtual void 			     TermGet( AT_Index::Iter const &rIter, byte *sDest, uint iDestLen, uint32 *pOccurrences = 0);

  AT_Record_List         Search( byte *sSearchString) const;

  // Integer index overrides AT_Index term search
  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;
};

class DRS_RoundIndex : public DRS_IntegerIndex
{
public:
  DRS_RoundIndex( AT_Index base, DRS_IndexDefInteger const &rIndexDef, uint prefPrecision);
  DRS_RoundIndex( const DRS_RoundIndex &rhs);
  ~DRS_RoundIndex();
  
  virtual AT_Index::Iter SeekTerm( byte *sSeekString);
  virtual void 			     TermGet( AT_Index::Iter const &rIter, byte *sDest, uint iDestLen, uint32 *pOccurrences = 0);

  // cloning
  virtual DRS_Index *clone
    ()
    const
    { return new DRS_RoundIndex(*this); };

  virtual DRS_Index * sort
    ()
    const
    //{ return new DRS_IntegerIndex(*round_index->getBaseIndex(), *this); }
	// AV: 
	{ return new DRS_IntegerIndex(*round_index, *this); }

  // override for rounding AV
  virtual AT_Index::Iter begin
    (AT_Num term)
    const
    { return round_index->begin(term); }
  virtual AT_Index::Iter begin
    (AT_String term = 0)
    const
    { return round_index->begin(term); }
  virtual AT_Index::Iter end
    ()
    const
    { return round_index->end(); }

  // override this to reflect preference precision AV
  virtual uint32          TermCountGet() const
    { return getTermCount(); };
  virtual uint32          getTermCount() const
    { return round_index->getTermCount(); };

  AT_Record_List         Search( byte *sSearchString) const;

  // Integer index overrides AT_Index term search
  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;

private:
  byte *RemoveDecimal
    (const byte *interm,
     uint *len = NULL) const;
  byte *InsertDecimal
    (const byte *interm,
     uint len);

  uint iPrefPrecision;
  // AT_Round_Index *round_index;
  // AT_Round_Index is not yet implemented
  AT_Index *round_index;
};

class DRS_QuantileIndex : public DRS_Index, public DRS_IndexDefInteger
{
public:
  DRS_QuantileIndex( DRS_Index &base, DRS_IndexDefInteger const &rIndexDef, AT_Quantile_List const &rQuantile, uint indexNum);
  DRS_QuantileIndex( const DRS_QuantileIndex & rhs);
  ~DRS_QuantileIndex();

  bool         			      IsSeekable() const { return false;}; //Only fixed-width integers can be seeked.
  inline bool             IsText() const { return false;};
  virtual AT_Index::Iter  SeekTerm( byte *sSeekString);
  virtual void 			      TermGet( AT_Index::Iter const &rIter, byte *sDest, uint iDestLen, uint32 *pOccurrences = 0);
  // override this to reflect preference precision AV
  virtual uint32          TermCountGet() const
    { return getTermCount(); };
  virtual uint32          getTermCount() const
    { return quant_index->getTermCount(); };

  // cloning
  virtual DRS_Index *clone
    ()
    const
    { return new DRS_QuantileIndex(*this); };

  //uint         			 Width() const { return 0;};

  // Quantile/Integer index overrides AT_Index term search
  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;

  //Note: 9/30/99. AT_Index::begin() made virtual so that AT_Quantile_Index can override.
  //For DRS_Quantile_Index, DRS_Index public AT_Index begin() gets called. So must override
  //AT_Index::begin() in DRS_QuantileIndex.
  virtual AT_Index::Iter begin
    (AT_Num term)
    const;
  virtual AT_Index::Iter begin
    (AT_String term = 0)
    const;
  virtual AT_Index::Iter end
    ()
    const;
    
private:
  AT_Quantile_Index *quant_index;
};


#endif
