
#ifndef XPACE_INDEX_C_H
#define XPACE_INDEX_C_H

#include "base/exception_c.h"

#include "result/result_c.h"

#ifdef __cplusplus
  #include "index/index.h"
  struct Xpace_Index
  {
    Xpace::Index *ix;
  };

  extern "C"
  {

#else
  typedef struct
  {
    void* v;
  }
  Xpace_Index;
#endif

/// Create a new index
/// #param config the Index's configuration
/// @retval the new index
XPACE_EXPORT Xpace_Error _stdcall Xpace_Index_Create
  (const Xpace_String config,
   Xpace_Index* result);

XPACE_EXPORT void _stdcall Xpace_Index_Destroy
    (Xpace_Index ix);

/// @retval the Index's configuration
XPACE_EXPORT Xpace_Error _stdcall Xpace_Index_getConfig
    (Xpace_Index ix,
     Xpace_String* result);

/// @retval the Index's Collator
//XPACE_EXPORT Xpace_Error _stdcall Xpace_Index_getCollator
//  (const Xpace_Index ix,
//   Xpace_Collator *const result);

/// @retval true iff the index is empty
XPACE_EXPORT Xpace_Error _stdcall Xpace_Index_isEmpty
    (const Xpace_Index ix,
     bool* result);

/// @retval the number of terms in the index
XPACE_EXPORT Xpace_Error _stdcall Xpace_Index_getTermCount
  (const Xpace_Index ix,
   uint64* result);

#ifdef XPACE_REFLISTCURSOR_C_H
XPACE_EXPORT Xpace_Error _stdcall Xpace_Index_Eval
  (const Xpace_Index ix,
   Xpace_String query,
   uint64 recCount,
   Xpace_RefListCursor* result);
#endif

// ================================== INDEX TERM ITERATOR =====

#if 0
/// @retval a string representation (from a Collator) of this index term
XPACE_EXPORT Xpace_Error _stdcall Xpace_Index_Term_Iter_getStr
  (const Xpace_Index_Term_Iter,
   Xpace_String *const result);

/// @retval this index key
XPACE_EXPORT Xpace_Error _stdcall Xpace_Index_Term_Iter_getKey
  (const Xpace_Index_Term_Iter,
   Xpace_Key *const result);

/// @retval the list of references for this index term
XPACE_EXPORT Xpace_Error _stdcall Xpace_Index_Term_Iter_getRefList
  (const Xpace_Index_Term_Iter,
   Xpace_RefList *const result);

/// @retval the list of all references for all index terms in the interval [*self, end)
XPACE_EXPORT Xpace_Error _stdcall Xpace_Index_Term_Iter_getRefListRange
	(const Xpace_Index_Term_Iter self,
   const Xpace_Index_Term_Iter end,
   Xpace_RefList *const result);

/// @retval true iff the iterator is past the end of the index's term list
XPACE_EXPORT Xpace_Error _stdcall Xpace_Index_Term_Iter_isEnd
  (const Xpace_Index_Term_Iter,
   bool* result);

/// @param delta move the iterator this far in the index list
/// @retval true if move successful, false (and don't move) if not
XPACE_EXPORT Xpace_Error _stdcall Xpace_Index_Term_Iter_Move
  (const Xpace_Index_Term_Iter,
   int64 delta,
   bool* result);

/// the distance between two iterators
/// @param rhs the other iterator
/// @retval the distance
XPACE_EXPORT Xpace_Error _stdcall Xpace_Index_Term_Iter_Diff
  (const Xpace_Index_Term_Iter self,
   const Xpace_Index_Term_Iter end,
   int64* result);

// ================================== SEARCH ==================

// find a key (or the next term in the index)

/// @retval an iterator to the 0-th term in the Index
XPACE_EXPORT Xpace_Error _stdcall Xpace_Index_Begin0
  (const Xpace_Index il,
   Xpace_Index_Term_Iter* result);

/// @param key find this String
/// @retval found true if key was found
/// @retval an iterator to the term in the Index corresponding to key (next if key is not found)
XPACE_EXPORT Xpace_Error _stdcall Xpace_Index_Begin_String
  (const Xpace_String key,
   const Xpace_Index il,
   bool* found,
   Xpace_Index_Term_Iter* result);

/// @param key find this int64
/// @retval found true if key was found
/// @retval an iterator to the term in the Index corresponding to key (next if key is not found)
XPACE_EXPORT Xpace_Error _stdcall Xpace_Index_Begin_Int
  (const int64 key,
   const Xpace_Index il,
   bool* found,
   Xpace_Index_Term_Iter* result);

/// @param key find this BytesRef
/// @retval found true iff key was found
/// @retval an iterator to the term in the Index corresponding to key (next if key is not found)
XPACE_EXPORT Xpace_Error _stdcall Xpace_Index_Begin_BytesRef
  (const Xpace_BytesRef key,
   const Xpace_Index il,
   bool* found,
   Xpace_Index_Term_Iter* result);

// search for a key, adding if it's not there

/// @param key find/add this String
/// @retval added true if key was added
/// @retval an iterator to the term in the Index corresponding to key 
XPACE_EXPORT Xpace_Error _stdcall Xpace_Index_Begin_Add_String
  (const Xpace_String key,
   const Xpace_Index il,
   bool* added,
   Xpace_Index_Term_Iter* result);

/// @param key find/add this int64
/// @retval added true if key was added
/// @retval an iterator to the term in the Index corresponding to key 
XPACE_EXPORT Xpace_Error _stdcall Xpace_Index_Begin_Add_String
  (const int64 key,
   const Xpace_Index il,
   bool* added,
   Xpace_Index_Term_Iter* result);

/// @param key find/add this BytesRef
/// @retval added true if key was added
/// @retval an iterator to the term in the Index corresponding to key 
XPACE_EXPORT Xpace_Error _stdcall Xpace_Index_Begin_Add_String
  (const BytesRef key,
   const Xpace_Index il,
   bool* added,
   Xpace_Index_Term_Iter* result);

/// @retval an iter one past the end
XPACE_EXPORT Xpace_Error _stdcall Xpace_Index_End
  (Xpace_Index_Term_Iter* result);

/// callback for each term in an index
/// @param key the term's key
/// @param callerInfo passed into Xpace_Index_forEach...
/// @return true to continue, false to stop
bool (Xpace_Index_forEachTerm*)
  (const Xpace_Key key,
   void* callerInfo);

/// callback for each reference in an index
/// @param ref a pointer to the first element in the ref list
/// @param len the number of elements in the ref
/// @param callerInfo passed into Xpace_Index_forEach...
/// @return true to continue, false to stop
bool (Xpace_Index_forEachRef*)
  (uint64 *const refs,
   size_t len,
   void* callerInfo);

/// traverse each term in the range [begin, end)
/// @param begin start here
/// @param end end here
/// @param termCallback if !=0 call this for each term
/// @retval true if completed, false if stopped by callback
XPACE_EXPORT Xpace_Error _stdcall Xpace_Index_forEachTermRange
  (const Xpace_Index,
   Xpace_Index_Term_Iter begin,
   Xpace_Index_Term_Iter end,
   Xpace_Index_forEachTerm termCallback,
   bool* result);

/// traverse the count terms starting at begin
/// @param begin start at the begin'th term
/// @param count for this many terms
/// @param termCallback if !=0 call this for each term
/// @retval true if completed, false if stopped by callback
XPACE_EXPORT Xpace_Error _stdcall Xpace_Index_forEachTermRange
  (const Xpace_Index,
   Xpace_Index_Term_Iter begin,
   uint64 count,
   Xpace_Index_forEachTerm termCallback,
   bool* result);

/// traverse each ref for terms in the range [begin, end)
/// @param begin start here
/// @param end end here
/// @param termCallback if !=0 call this for each term
/// @param refCallback if !=0 call this for each ref
/// @retval true if completed, false if stopped by callback
XPACE_EXPORT Xpace_Error _stdcall Xpace_Index_forEachRefRange
  (const Xpace_Index,
   Xpace_Index_Term_Iter begin,
   Xpace_Index_Term_Iter end,
   Xpace_Index_forEachTerm termCallback,
   Xpace_Index_forEachRef refCallback,
   bool* result);

/// traverse each ref for terms in the range [begin, begin + count)
/// @param begin start here
/// @param count for this many terms
/// @param termCallback if !=0 call this for each term
/// @param refCallback if !=0 call this for each ref
/// @retval true if completed, false if stopped by callback
XPACE_EXPORT Xpace_Error _stdcall Xpace_Index_forEachRefRange
  (const Xpace_Index,
   uint64 begin,
   uint64 count,
   Xpace_Index_forEachTerm termCallback,
   Xpace_Index_forEachRef refCallback,
   bool* result);
#endif

/// Get a range of index terms (and counts, if any)
/// @param begin the first term to get
/// @param count get (at most) this many terms
/// @param includeCounts if there are counts in the index, include them in the result
/// @retval the terms (and counts)
XPACE_EXPORT Xpace_Error _stdcall Xpace_Index_getTerms
  (const Xpace_Index ix,
   uint64 begin,
   uint64 count,
   bool includeCounts,
   Xpace_Table_Result* result);

#ifdef __cplusplus
}
#endif

#endif
