#ifndef __DBALNIMAGE_H__
#define __DBALNIMAGE_H__

#include "dbtable.h"
#include "image2d.h"
#include "wltcompress.h"
#include "wavelet.h"
#include <set>

#ifndef QUANTIZEFACTOR
#define QUANTIZEFACTOR 16777216
#endif

/**
 * database setup
 * mydb : store how each set of alignment images are transformed
 * [alignset_key] -> [alignment data]
 *
 * mydb_image
 * [alignimg_key] -> [image]
 * id in key references the alignment set in mydb
 */
class dbalnimage : public dbtable
{
 public:
  struct alignimg_key
  {
    int id;
    int slice;
    int channel;
  };

  struct image_conn
  {
    int a;
    int b;
    int lowx;
    int lowy;
    int highx;
    int highy;
  };

  dbalnimage();
  virtual ~dbalnimage();
  virtual int close();
  virtual int init( DbEnv *env );

  /// check if aid exists
  int checkaid( int aid );

  int getslices( int aid, std::vector< int > &sli );
  int getchannels( int aid, std::vector< int > &chs );

  int get_slices( int aid, std::set< int > &sli );
  int get_channels( int aid, std::set< int > &chs );

  /// create the first align set
  /**
   * parameters are a list of row, column, xtransform, y-transform
   * showing how each tile in the original tiled image are transformed
   *
   * @return alignset id
   */
  int create_firstaln_set( std::vector< int > &row,
                           std::vector< int > &col,
                           std::vector< int > &x,
                           std::vector< int > &y);

  /// adds an aligned image
  int add_aligned_image( int aid, int slice, int channel, image2d *image );

  /// gests an aligned image
  int get_aligned_image( int aid, int slice, int channel, image2d *image );

  /// sets an alignment mask specifiying which pixels have values
  int set_aligned_mask( int aid, image2d *image );

  int get_aligned_mask( int aid, image2d *image );

  /// crate a new alignment set
  /**
   * @return alignset id
   */
  int create_align( int iteration,
                    std::vector< int > &ids,
                    std::vector< int > &x,
                    std::vector< int > &y );

  /// return list of ids for align sets for given iteration
  int get_align_sets( int iteration, 
                      std::vector< int > &ids);

  int get_imconnection( int iteration,
                        std::vector< image_conn > &connections );

  int set_imconnection( int iteration,
                        std::vector< image_conn > &connections );

  int deleteaid( int daid );
  int deleteconnection( int iter );

  int get_alignedset_data( int aid, int &iteration, 
                           std::vector< int > &ids,
                           std::vector< int > &xtrans,
                           std::vector< int > &ytrans );

  int encodeto1d( int a, int b )
  {
    return a*32+b;
  }

  int decodeto2d( int in, int &a, int &b)
  {
    a = in/32;
    b = in %32;
    return 0;
  }

 private:

  /// read alignset data
  int read_alignset_data( char *data, int len,
                          int &iteration,
                          std::vector< int > &ids,
                          std::vector< int > &xtrans,
                          std::vector< int > &ytrans );

  int get_basetiles( std::vector< int > &id, 
                     std::vector< std::pair< int, int > > &base );

  /// pack data for alignset table
  /**
   * [iteration][num. tiles][ tile and alignment ]
   * [32bit int][32bit int ][ (num. tiles)*(itemsz) ]
   *
   * tile and alignment:
   * [tile id][xtrans][ytrans]
   * [32bit int][32bit int][32bit int]
   *
   * encoding of tile_id for iteration 0: 
   * done with encodeto1d and decodeto2d functions
   *
   * @param iteration iteration number 
   * @param ids vector of ids pointing back to the same table for the image or orig tile
   * @param xtrans vector of translations in the x dimention for corresponding image
   * @param ytrans same as xtrans but for y direction
   */
  int create_alignset_data( int iteration,
                            std::vector< int > &ids,
                            std::vector< int > &xtrans,
                            std::vector< int > &ytrans,
                            char **data, int &len );

  Db *mydb_image;

  Db *mydb_image_id_idx;
  Db *mydb_image_channel_idx;

  Db *mydb_image_mask;

  Db *mydb_image_conn;

  Db *mydb_iter_idx;
};

#endif
