
/**********************************************************//**
 **
 ** @file index/indexlist.h
 **
 ** Copyright (C) 2009  Xpace, LLC.  All rights reserved
 **
 ** www.xpace.net
 **
 **************************************************************/

#if !defined XPACE_INDEXLIST_H
#define XPACE_INDEXLIST_H

#include <vector>
#include <map>

#include "base/config.h"
#include "index/index.h"

namespace Xpace
{
  class indexListImpl;

  class XPACE_EXPORT IndexList : public Configurable
  {
  public :
    /// An empty index list
    IndexList
      ();

    /// open an already-existing index list,
    /// or create one with this Configuration
    /// @param config the Configuration
    /// @param overwrite if true, delete if list already exists
    /// @throw CantOpen
    explicit IndexList
      (const Configuration& config,
       bool overwrite = false);      

    /// create a new reference to a list
    /// @param rhs the list
    IndexList
      (const IndexList& rhs);
    /// make this refer to a list
    /// @param rhs the list
    IndexList& operator=
      (const IndexList& rhs);
    
    ~IndexList
      ();

    /// @return the number of indexes in the list
    size_t getCount
      ()
      const;

    /// Get the Configuration of an index
    /// @param the index number
    /// @return the index's Configuration
    const Configuration& getIndexConfig
      (size_t indexNum)
      const;

    /// open an index by name
    /// @param indexName the index to get
    /// @retval indexNum fill in the index's number
    /// @return the found index, Index() if not found
    Index& openIndex
      (const String& indexName,
       uint* indexNum = 0,
       Configuration config = Configuration());
    const Index& openIndex
      (const String& indexName,
       uint* indexNum = 0,
       Configuration config = Configuration())
      const;

    /// open an index by number
    /// @param indexNum the number of the index to get
    /// @param config if != Configuration(), override index's Configuration with this one
    /// @return the found index, Index() if not found
    Index& openIndex
      (uint indexNum,
       Configuration config = Configuration());   
    const Index& openIndex
      (uint indexNum,
       Configuration config = Configuration())
      const;   

    /// @param index index to add
    /// @return number of added index
    uint addIndex
      (Index& index);

    #ifdef XPACE_REFLIST_H
    /// @param query a query string
    /// @param recCount for NOT searches
    /// @return a RefListCursor into the result
    RefListCursor eval
      (String query,
       uint64 recCount = 0)
      const;
    
    #ifdef QDOM_H
    /// @param query a search tree
    /// @param recCount for NOT searches
    /// @return a RefListCursor into the result
    RefListCursor eval
      (QDomNode query,
       uint64 recCount = 0)
      const;
    #endif
    #endif

    #if defined(XPACE_SCURSOR_H) || defined(XPACE_TABLECURSOR_H)  

    /// bulk build

    /// status callback 
    struct buildStatus
    {
      buildStatus
	    () :
	      interval(1000000),
	      maxMemory(size_t(-1)),
	      memUsed(0)
	    {
      }

      virtual ~buildStatus() 
      { 
      }

      /// @param how many refs indexed
      /// @param term how many terms indexed
      /// @param unique how many unique terms indexed
        /// @return true to continue, false to stop
      virtual bool operator()
	      (uint64 ref,
	       uint64 term,
	       uint64 unique)
      = 0;
	    uint interval;      ///< fillin - call operator() every this many refs
	    size_t maxMemory;   ///< fillin - use no more than this much memory
	    size_t memUsed;     ///< how much memory is actually being used by this build
    };
    #endif

    #if defined(XPACE_SCURSOR_H)
    /// @param src build from this SCursor
    /// @param bst build status callback
    /// @param wst write status callback (for temp files)
    /// @return true if completed, false if stopped by callback
    bool build
      (SCursor* src,
	     buildStatus* st = 0,
       Index::writeStatus* wst = 0);
    #endif

    #if defined(XPACE_TABLECURSOR_H)
    /// @param src build from this SCursor
    /// @param bst build status callback
    /// @param wst write status callback (for temp files)
    /// @return true if completed, false if stopped by callback
    bool build
      (TableCursor* src,
	     buildStatus* st = 0,
       Index::writeStatus* wst = 0);
    #endif

    /// write in current state
    /// @param wst write status callback
    /// @return true if successful and complete, false if failed or stopped by callback
    bool write
      (Index::writeStatus* st = 0);

    /// speed up range search for indexes in a list
    /// @param config specifies from/to files, indexes to be oprimized
    /// @return true if successful, false if failed of stopped by callback
    bool range
      (const Configuration& config,
       Index::writeStatus* st = 0);

    /// merge a list of index lists
    /// @param config merge to a new index list with this configuration
    /// @param list list of lindx lists to merge
    /// @return true if successful and complete, false if failed or stopped by callback
    static
    bool merge
      (const Configuration& config,
       const std::vector<IndexList*>& list,
       Index::writeStatus* st = 0);

    class cantOpen : public Exception
    {
    public :
      cantOpen
        (Configuration conf,
         const Exception /*reason*/) :
          Exception("Cannot open index list from configuration \"%1\".")
      {
        addParam(conf.toString());
      }; 
    };

  private :
    friend class indexListImpl;
    indexListImpl* impl;
  };

  #if (defined TESTING || !defined NDEBUG) && !defined DOCUMENTATION
  void XPACE_EXPORT testIndexes
    (File* configFile,
     uint checks);
  #endif

} // namespace

#endif

