#ifndef __DBFEATURESIFT_H__
#define __DBFEATURESIFT_H__

#include "featuresift.h"
#include "dbtable.h"
#include "pthread.h"
#include <queue>
#include <math.h>

/// image sift database
class dbfeaturesift : public dbtable
{
 public:
  struct fkey
  {
    unsigned long long int fid;
  };
  struct imfkey
  {
    unsigned long long int fid;
  };
  struct imfvalue
  {
    int aid;
    int slice;
    int channel;
    double size;
  };

  dbfeaturesift();

  virtual ~dbfeaturesift();

  virtual int close();

  virtual int init( DbEnv *env );

  int addfeature( unsigned long long int fid, 
                  imfvalue imfv, double *d, int sz );

  /// return next sequencial fid
  unsigned long long int nextfid( );

  /// adds a feature
  unsigned long long int addfeature( int aid,
                                     int slice,
                                     int channel,
                                     featuresift &f );

  int getfeature( featuresift &f,
                  unsigned long long int aid );

  int getfeaturelist( std::vector<unsigned long long int> &f,
                      int aid, int slice,
                      int channel );

 private:
  Db *imfdb;
  /// aid idx
  Db *imf_aididx;
  /// slice idx
  Db *imf_sliceidx;
  /// channel index
  Db *imf_channelidx;
  /// aid, slice, channel index
  Db *imf_ascidx;
};

struct imsift_data
{
  dbfeaturesift::imfvalue key;
  double *data;
  int dlen;
};

/// data structure for threaded sift db insert
struct dbfeaturesift_insert_td
{
  pthread_t tid;
  std::queue< imsift_data > toinsert;
  pthread_mutex_t *toinsert_lock; ///< queue lock
  pthread_cond_t *toinsert_cond;  ///< conditonal
  unsigned long long int cid;     ///< current fid
  dbfeaturesift *dbsift;
  int endflag;

};

void *start_pthread_dbinsert( void *d );
int pthread_dbinsert( dbfeaturesift_insert_td *d );

#endif
