/** @file pswarp.h
 *
 *  @brief
 *
 *  @ingroup pswarp
 *
 *  @author IfA
 *  @version $Revision: 1.18 $ $Name: not supported by cvs2svn $
 *  @date $Date: 2009-02-06 03:10:36 $
 *  Copyright 2009 Institute for Astronomy, University of Hawaii
 */

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <stdio.h>
#include <string.h>
#include <strings.h>  // for strcasecmp
#include <unistd.h>   // for unlink
#include <pslib.h>
#include <psmodules.h>
#include <psphot.h>

#define THREADED 1

#include "pswarpErrorCodes.h"
#define PSWARP_RECIPE  "PSWARP" ///< Name of the recipe to use
#define PSASTRO_RECIPE "PSASTRO" ///< Name of the recipe to use

#define PSWARP_ANALYSIS_VARFACTOR "PSWARP.VARFACTOR" ///< Name for variance factor in analysis metadata
#define PSWARP_ANALYSIS_GOODPIX   "PSWARP.GOODPIX" ///< Name for number of good pixels in analysis metadata
#define PSWARP_ANALYSIS_COVARIANCES "PSWARP.COVARIANCES" ///< Name for covariance matrices on analysis MD

/**
 * a single pswarpMap converts coordinates from one image to a second image
 * the linear model is only valid over a limited range of pixels
 */
typedef struct {
    double Xo, Xx, Xy;
    double Yo, Yx, Yy;
    int xo;
    int yo;
} pswarpMap;

/* the pswarpMapGrid carries a collection of pswarpMag structures representing
 * the local value of the pswarpMap at different locations in the image.
 */
typedef struct {
    pswarpMap ***maps;
    int nXpts, nYpts;                   ///< number of x,y samples in the grid
    int nXpix, nYpix;                   ///< x,y spacing in src image pixels of grid samples
    double xMin,  yMin;                 ///< coordinate of first grid sample
} pswarpMapGrid;

typedef struct {
    /** values which are common to all tilesa */
    pmReadout *input;
    pmReadout *output;
    pswarpMapGrid *grid;
    psImageInterpolation *interp;
    psImage *region;

    /** input values for this tile */
    int gridX;
    int gridY;

    /** output values for this tile */
    long goodPixels;                    ///< Number of good pixels
    int xMin, xMax, yMin, yMax;         ///< Bounds of tile
    psKernel *covariance;               ///< Covariance matrix
} pswarpTransformTileArgs;

pswarpTransformTileArgs *pswarpTransformTileArgsAlloc(void);
bool pswarpTransformTile (pswarpTransformTileArgs *args);

pmConfig *pswarpArguments (int argc, char **argv);
bool pswarpOptions(pmConfig *config);
bool pswarpSetMaskBits (pmConfig *config);
bool pswarpParseCamera (pmConfig *config);
bool pswarpDefine (pmConfig *config);
bool pswarpLoop (pmConfig *config, psMetadata *stats);
psExit pswarpExitCode(psExit exitValue);
bool pswarpTransformReadout (pmReadout *output, pmReadout *input, pmConfig *config);
bool pswarpTransformSources(pmReadout *output, pmReadout *input, pmConfig *config);

bool pswarpMatchRange (int *minX, int *minY, int *maxX, int *maxY, pmReadout *dest, pmReadout *src);

pswarpMap *pswarpMapAlloc (void);
pswarpMapGrid *pswarpMapGridAlloc (int Nx, int Ny);

pswarpMapGrid *pswarpMapGridFromImage (pmReadout *dest, pmReadout *src, int nXpix, int nYpix);
bool pswarpMapGridSetGrid (pswarpMapGrid *grid, int ix, int iy, int *gridX, int *gridY);
bool pswarpMapGridCoordRange (pswarpMapGrid *grid, int gridX, int gridY, psPlane *min, psPlane *max);
int pswarpMapGridNextGrid_X (pswarpMapGrid *grid, int gridX);
int pswarpMapGridNextGrid_Y (pswarpMapGrid *grid, int gridY);
double pswarpMapGridMaxError (pswarpMapGrid *grid);
bool pswarpMapApply (double *outX, double *outY, pswarpMap *map, double inX, double inY);
bool pswarpMapSetLocalModel (pswarpMap *map, pmReadout *dest, pmReadout *src, int ix, int iy);

bool pswarpDefineSkycell (pmFPAfile **outFile, pmConfig **outConfig, pmConfig *config,
                          const char *filename, const char *argname);

/// Get the range of lit pixels
bool pswarpPixelsLit(const pmReadout *readout, ///< Readout to inspect
                     psMetadata *stats, ///< Statistics to update with the result
                     const pmConfig *config ///< Configuration
    );

/**
 * define threads for this program
 */
bool pswarpSetThreads (void);

/// Return software version
psString pswarpVersion(void);

/// Return software souce
psString pswarpSource(void);

/// Return long software version information
psString pswarpVersionLong(void);

/// Populate header with version information
bool pswarpVersionHeader(
    psMetadata *header                  ///< Header to populate
    );

/// Print version information
void pswarpVersionPrint(void);

/// Activate a list of files
///
/// File list must be NULL-terminated
void pswarpFileActivation(pmConfig *config, // Configuration
                          char **files, // Files to turn on/off
                          bool state   // Activation state
    );


// Run down the FPA hierarchy, checking files
bool pswarpIOChecksBefore(pmConfig *config // Configuration
    );

// Run up the FPA hierarchy, checking files
bool pswarpIOChecksAfter(pmConfig *config // Configuration
    );

