#ifndef PAP_FOCAL_PLANE_H
#define PAP_FOCAL_PLANE_H

#include "pslib.h"
#include "papStuff.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
} papFPA;

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)
    papFPA *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
} papChip;

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)
    papChip *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
} papCell;


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
} papReadout;


// Look for a particular value for a given cell (referred to by FPA+chip+cell)
psMetadataItem *psCellGetValue(papCell *cell, // The cell
			       const char *valueName // Name of value
    );

// Type-specific functions provided as a convenience to the user
float psCellGetValueF32(papCell *cell, // The cell
			const char *valueName // Name of value
			);
int psCellGetValueS32(papCell *cell, // The cell
		      const char *valueName // Name of value
		      );
double psCellGetValueF64(papCell *cell, // The cell
			 const char *valueName // Name of value
			 );
psString psCellGetValueString(papCell *cell, // The cell
			      const char *valueName // Name of value
			      );


// Allocators and deallocators
papFPA *papFPAAlloc(const psMetadata *camera, // Camera configuration
		    psDB *db		// Database
    );
void p_papFPAFree(papFPA *fpa);

papChip *papChipAlloc(papFPA *fpa	// FPA to which the chip belongs
    );
void p_papChipFree(papChip *chip);

papCell *papCellAlloc(papChip *chip	// Chip to which the cell belongs
    );
void p_papCellFree(papCell *cell);

papReadout *papReadoutAlloc(papCell *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_papReadoutFree(papReadout *readout);

#endif
