#ifndef __TILE_H__
#define __TILE_H__

#include "image2d.h"
#include "image3d.h"
#include "dbimage.h"
#include "dbalnimage.h"
#include "transformation.h"

/// describes a tile in the overall image
/**
 * confocal image acquasion row by row
 * tile a1 and a2 are aligned only by an y transform
 * row a and row b require transform by x and y
 * +--> y
 * | +--+--+--+--+
 * | |a1|a2|a3|a4| 
 * V |  |  |  |  |
 * x +--+--+--+--+
 *   |  |b1|b2|  |
 *   |  |  |  |  |
 *   +--+--+--+--+
 *   |  |  |  |  |
 *   |  |  |  |  |
 *   +--+--+--+--+
 */
class tile
{
 public:
  /// describes the tile transform
  struct tiletrans
  {
    tile *mytile;  ///< pointer to the tile
    transformation ts;
  };
  tile();
  ~tile();

  /// initialize the tile
  /**
   * @param xcoor x cooridinate of the tile x \in [A-Z]
   * @param ycoor y cooridinate of the tile y \in [1-9]
   * @param db pointer to the image storage
   */
  int init( char xcoor, char ycoor, dbimage *db );

  /// initialize the tile using integers
  int init( int xcoor, int ycoor, dbimage *db );

  /// initialize the tile using 
  int init( int aid, dbalnimage *alndb );

  /// align this tile to another one
  /**
   * produces a transformation that to apply to the other tile
   */
  int align( tile *ot, std::vector< transformation > &ts );

  int getimages( std::vector< int > &ids,
                 std::vector< image2d *> &ims );

  /// gets a list of images based on a input of [slice, channel] pairs
  int getimages( std::vector< std::pair<int, int> > &ids,
                 std::vector< image2d *> &ims );

  /// returns list of slice numbers and channels
  int getids( std::vector< int > &slice,
              std::vector< int > &channel );

  int getimage( int slice, int channel, image2d *im );

  int getsize( int &height, int &width );

  /// return the height of images in this tile
  int getheight();

  /// return the width of images in this tile
  int getwidth();

  int getmap( image2d *im );

  int xcoor()
  {
    return tidx;
  }
  int ycoor()
  {
    return tidy;
  }

  int getaid()
  {
    return aid;
  }

 private:
  tiletrans left;  ///< the tile to the left of this one
  tiletrans right; ///< tile to the right
  
  std::vector< tiletrans > top;  ///< tiles to the top
  std::vector< tiletrans > bottom; ///< tiles to the bottom

  int tidx;  ///< "0123..."
  int tidy;  ///< "0123..."

  dbimage *idb; ///< database where to get the images

  int aid;          ///< aligned image id
  dbalnimage *adb;  ///< aligned image database

  int nslices;  ///< number of slices in the stack
};

#endif
