#ifndef PM_FPA_H
#define PM_FPA_H

#include "pslib.h"
#include "psAdditionals.h"

// Temporary metadata types
#define PS_META_CHIP PS_META_UNKNOWN
#define PS_META_CELL PS_META_UNKNOWN

typedef struct {
    // Astrometric transformations
    psPlaneDistort* fromTangentPlane;	// Transformation from tangent plane to focal plane
    psPlaneDistort* toTangentPlane;	// Transformation from focal plane to tangent plane
    psProjection *projection;		// Projection from tangent plane to sky
    // Information
    psMetadata *values;			// Important values (cached)
    const psMetadata *camera;		// Camera configuration
    psDB *db;				// Database
    psArray *chips;			// The chips
    // FITS data
    const char *extname;		// Extension name, if it corresponds to this level
    psArray *pixels;			// The pixel data, if it corresponds to this level
    psMetadata *header;			// The FITS header, if it corresponds to this level
} pmFPA;

typedef struct {
    // Offset specifying position on focal plane
    const int col0;			// Offset from the left of FPA
    const int row0;			// Offset from the bottom of FPA
    // Astrometric transformations
    psPlaneTransform* toFPA;		// Transformation from chip to FPA coordinates
    psPlaneTransform* fromFPA;		// Transformation from FPA to chip coordinates
    // Information
    psMetadata *values;			// Important values (cached)
    psArray *cells;			// The cells (referred to by name)
    pmFPA *parent;			// Parent FPA
    // FITS data
    const char *extname;		// Extension name, if it corresponds to this level
    psArray *pixels;			// The pixel data, if it corresponds to this level
    psMetadata *header;			// The FITS header, if it corresponds to this level
} pmChip;

typedef struct {
    // Offset specifying position on chip
    const int col0;			// Offset from the left of chip
    const int row0;			// Offset from the bottom of chip
    // Astrometric transformations
    psPlaneTransform* toChip;		// Transformations from cell to chip coordinates
    psPlaneTransform* fromChip;		// Transformations from cell to chip coordinates
    psPlaneTransform* toFPA;		// Transformations from cell to FPA coordinates
    psPlaneTransform* toTP;		// Transformations from cell to FPA coordinates
    psPlaneTransform* toSky;		// Transformations from cell to tangent plane coordinates
    // Information
    psMetadata *values;			// Important values (cached)
    psArray *readouts;			// The readouts (referred to by number)
    pmChip *parent;			// Parent chip
    // FITS data
    const char *extname;		// Extension name, if it corresponds to this level
    psArray *pixels;			// The pixel data, if it corresponds to this level
    psMetadata *header;			// The FITS header, if it corresponds to this level
} pmCell;


typedef struct {
    // Details for position on the cell
    const int col0;			// Offset from the left of cell.
    const int row0;			// Offset from the bottom of cell.
    const int colParity;		// Readout Direction X
    const int rowParity;		// Readout Direction Y
    const unsigned int colBins;		// Amount of binning in x-dimension
    const unsigned int rowBins;		// Amount of binning in y-dimension
    // Information
    psImage *image;			// The pixels
    psList *overscans;			// Array of subimages containing the overscan region(s)
    psMetadata *values;			// readout-level metadata
} pmReadout;

// Allocators and deallocators
pmFPA *pmFPAAlloc(const psMetadata *camera, // Camera configuration
		  psDB *db		// Database
    );
void p_pmFPAFree(pmFPA *fpa);

pmChip *pmChipAlloc(pmFPA *fpa,	// FPA to which the chip belongs
		    psString name	// Name of chip
    );
void p_pmChipFree(pmChip *chip);

pmCell *pmCellAlloc(pmChip *chip,	// Chip to which the cell belongs
		    psMetadata *values,	// Initial values for concepts
		    psString name	// Name of cell
    );
void p_pmCellFree(pmCell *cell);

pmReadout *pmReadoutAlloc(pmCell *cell,	// Cell to which the readout belongs
			  int readoutNum, // Number of the readout
			  psImage *image, // The pixels
			  psList *overscans, // The overscan images
			  int col0, int row0, int colParity, int rowParity, int colBin, int rowBin // Data
    );
void p_pmReadoutFree(pmReadout *readout);

#endif
