
//
// AT_RECLIST.H -- Record lists, the result of a search.
//
// A search (from AT_Index) results in an AT_Record_List.  Record lists
// may be combined through binary boolean operators and, or, xor, and without,
// and inverted through unary boolean operator not.
//
// Access to a record list is through a random-access iterator, as well as the
// member functions count() and hasRecord().  count() could be rather slow, if
// record counts were not saved at indexing time, and, in general, forward-access
// (operator++, operator*) will be much faster than random-access.
//

#ifndef AT_RECLIST_H
#define AT_RECLIST_H

#include <iterator>

#include "base/at_defs.h"
#include "base/at_objects.h"

#include "index/reflist/reflist.h"

#include "x_at_index.h"

// ================================== RECORD LIST =============

namespace Xpace
{
  class RefListCursor;
};


class SEARCH_DECL AT_Index;
class termList;

class SEARCH_DECL AT_Record_List
{
  friend AT_Index;

public :
  // empty list
  AT_Record_List
    (uint32 numRecords);

  // from single term
  AT_Record_List
    (AT_Index::Iter& iter);

  // from range of terms
  AT_Record_List
    (AT_Index::Iter& start,
     AT_Index::Iter& end);

  AT_Record_List
    (const AT_Record_List& rhs);
  AT_Record_List& operator=
    (const AT_Record_List &rhs);

  ~AT_Record_List
    ();

  bool operator==
    (const AT_Record_List &rhs)
    const;
  bool operator!=
    (const AT_Record_List &rhs)
    const;

  bool operator!
    ();

  // number of records in list
  uint32 count
    ()
    const;

  // number or records in database
  uint32 dbRecords
    ()
    const;

  // is absRecNum in this rec list?
  // if so, return true, fill in relRecNum
  bool hasRecord
    (uint32 absRecNum,
     uint32 *relRecNum = 0)
    const;

  // add a record
  AT_Record_List& operator+=
    (uint32 recNum);

  // remove a record
  AT_Record_List& operator-=
    (uint32 recNum);

  // "and"
  AT_Record_List& operator&=
    (const AT_Record_List& rhs);

  // "or"
  AT_Record_List& operator|=
    (const AT_Record_List& rhs);

  // "xor"
  AT_Record_List& operator^=
    (const AT_Record_List& rhs);

  AT_Record_List& invert
    (uint dbRecordCount = 0);

  // "without"
  AT_Record_List& operator-=
    (const AT_Record_List& rhs);

  // sort
  class SEARCH_DECL Sort_Context
  {
    friend AT_Record_List;
    friend termList;

  public :
    enum unindexedAct
    {
      unindexedDrop = 0,
      unindexedToTop = 1,
      unindexedToBottom = 2
    };

    Sort_Context
      (AT_Index * index = 0,
       bool ascend = true,
       uint keepUnindexed = unindexedDrop,
       bool keepDuplicates = false)
    { assert(0); };
    Sort_Context
      (const Sort_Context& rhs)
    { assert(0); };

    ~Sort_Context
      ()
    {};
        
    Sort_Context& operator=
      (const Sort_Context& rhs)
    { return *this; };

    const AT_Index& getIndex
      ()
      const
    { return AT_Index::null; };
  };

  void sort
    (const Sort_Context* contexts,    // 0 = unsort
     uint numContexts,
     reportProgress* prog)
  { assert(0); };

  // count unique number of terms in the record list
  uint term_count
    (AT_Index & index,
     reportProgress * prog)
  { assert(0); return 0; };

  // iterators
  class SEARCH_DECL Iter;
  const Iter begin
    ()
    const;
  const Iter end
    ()
    const;

  static const AT_Record_List null;

  Xpace::RefListCursor x_RefList;
  uint db_records;
  AT_Record_List
    (Xpace::RefListCursor& x,
     uint dbRecords) :
      x_RefList(x),
      db_records(dbRecords)
  {};
};

// ================================== RECORD LIST ITERATOR ====

class SEARCH_DECL AT_Record_List::Iter 
{
public :
  Iter
    ();
  Iter
    (const Iter& rhs);
  Iter& operator=
    (const Iter& rhs);
  ~Iter
    ();

  static AT_Record_List::Iter null;

  // fast access
  uint32 operator*
    ()
    const;

  // fast navigation
  Iter& operator++
    ();

  // possibly slow navigation

  Iter operator++
    (int);

  virtual Iter& operator--
    ();
  Iter operator--
    (int);

  Iter& operator+=
    (int32 n);
  Iter& operator-=
    (int32 n);

  Iter operator+
    (int32 n)
    const;
  Iter operator-
    (int32 n)
    const;

  // comparison

  int32 operator-
    (const Iter& rhs);
  bool operator==
    (const Iter& rhs)
    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;
  bool operator>=
    (const Iter& rhs)
    const;

  // random, likely slow, access
  uint32 operator[]
    (uint32 i);

  Xpace::RefListCursor x_RefList;
  uint db_records;
  Iter
    (Xpace::RefListCursor x,
     uint dbRecords) :
      x_RefList(x),
      db_records(dbRecords)
  {
  };
};

#endif
