#ifndef __mango_oracle_index_parallel_h__
#define __mango_oracle_index_parallel_h__

#include "base_cpp/os_sync_wrapper.h"
#include "oracle/bingo_oracle_parallel.h"
#include "oracle/mango_oracle.h"

#include <string>
#include <vector>

using namespace indigo;

//
// Classes for parallelized index creation
//

class MangoRegisterDispatcher : public BingoOracleDispatcher
{
public:
   MangoRegisterDispatcher (MangoOracleContext &context, 
      OracleEnv &env, const char *rowid);

protected:
   virtual OsCommand*         _allocateCommand ();
   virtual OsCommandResult*   _allocateResult  ();

   virtual bool _setupCommand    (OsCommand &command);
   virtual void _addCurrentRecordToCommand (BingoOracleCommand &command);
   virtual void _handleResult (OsCommandResult  &result); 

   MangoOracleContext &_context;
   OracleEnv &_env;
   const char *_rowid;
   int  _molecules_prepared, _molecules_saved;
   OsLock _lock_for_exclusive_access;
};

class MangoRegisterCommand : public BingoOracleCommand
{
public:
   MangoRegisterCommand (OracleEnv &env, MangoOracleContext &context,
      OsLock &lock_for_exclusive_access, int *molecules_prepared_counter);

   virtual void execute (OsCommandResult &result);

   virtual void clear ();

   ChunkStorage rowids;
private:
   MangoOracleContext &_context;
   OracleEnv          &_env;
   OsLock             &_lock_for_exclusive_access;
   int                *_molecules_prepared_counter;
};

struct MangoRegisterFailure
{
   std::string rowid, message;
};

class MangoRegisterResult : public OsCommandResult
{
public:
   int valid_molecules;

   virtual void clear ();

   ObjArray<MangoIndex> per_molecule_index;
   std::vector<MangoRegisterFailure> warnings;
   ChunkStorage per_molecule_data;
   ChunkStorage rowids;
}; 


bool mangoPrepareMolecule (OracleEnv &env, const char *rowid,
                            const Array<char> &molfile_buf,
                            MangoOracleContext &context,
                            MangoIndex &index,
                            Array<char> &data,
                            OsLock *lock_for_exclusive_access, 
                            std::string &failure_message);

void mangoRegisterMolecule (OracleEnv &env, const char *rowid,
                             MangoOracleContext &context,
                             const MangoIndex &index,
                             BingoFingerprints &fingerprints,
                             const Array<char> &prepared_data,
                             bool append);

#endif // __mango_oracle_index_parallel_h__
