#ifndef STAC_H
#define STAC_H

#include "pslib.h"

#define abs(x) ((x) >= 0 ? (x) : (-(x)))

#define MAXCHAR 80

// Temporary implementation
psPlaneTransform *psPlaneTransformAlloc(psS32 n1, psS32 n2);

/************************************************************************************************************/

// stacConfig.c

// Configuration options
typedef struct {
    int verbose;			// Verbosity level
    float gain, readnoise;		// Gain and readnoise for detectors
    psArray *inputs;			// Input file names
    const char *output;			// Output file name
    int outnx, outny;			// Size of output image
    float saturated;			// Saturation level
    float bad;				// Bad level
    float reject;			// Rejection level
    float frac;				// Fraction of input pixel that must be masked before the pixel is
					// considered bad
} stacConfig;

// Allocator
stacConfig *stacConfigAlloc(void);
// Deallocator
void stacConfigFree(stacConfig *config);

// Help message
void help(const char *name);

// Parse the command line and return config
stacConfig *stacParseConfig(int argc,	// Number of command-line arguments
			    char **argv // Command-line arguments
    );


/************************************************************************************************************/

// stacRead.c

// Read the input files and return an array of images
psArray *stacReadImages(stacConfig *config);

// Read the map files and return an array of transformations
psArray *stacReadMaps(stacConfig *config);

/************************************************************************************************************/

// stacErrorImages.c

// Calculate the error images
psArray *stacErrorImages(psArray *inputs, // Array of input images
			 stacConfig *config // Configuration details
    );

/************************************************************************************************************/

// stacTransform.c

// Transform input images
psArray *stacTransform(const psArray *images, // Array of images to be transformed
		       const psArray *maps, // Array of polynomials that do the transformation
		       const psArray *errors, // Array of error images
		       psArray **outErrors, // Array of output errors
		       const psArray *masks, // Masks of input images
		       const stacConfig *config	// Configuration
    );

/************************************************************************************************************/

// stacCheckMemory.c

// Check memory
void stacCheckMemory(void);

// Print out the problem
void stacMemoryProblem(const psMemBlock* ptr, ///< the pointer to the problematic memory block.
		       const char *file, ///< the file in which the problem originated
		       psS32 lineno	///< the line number in which the problem originated
    );

// Print out a memblock when it's allocated --- this function used as a callback
psMemoryId stacMemPrint(const psMemBlock *ptr);


/************************************************************************************************************/

// stacCombine.c

// Get the mean for a bunch of values
float stacCombineMean(psVector *values,	// Values for which to take the mean
		      psVector *errors,	// Errors in the values
		      psVector *masks	// Masks for the values, 0 = don't use, 1 = use
    );

// Get the median for a bunch of values
float stacCombineMedian(psVector *values, // Values for which to take the median
			psVector *errors, // Errors in the values
			psVector *masks	// Masks for the values, 0 = don't use, 1 = use
    );

// Combine the transformed images
psImage *stacCombine(psArray *images,	// Array of transformed images
		     psArray *errors,	// Array of transformed error images
		     int nReject,	// Number of rejection iterations
		     psArray **rejected, // Array of rejection masks
		     stacConfig *config	// Configuration
    );

/************************************************************************************************************/

// stacInvertMaps.c

// Invert an array of maps
psArray *stacInvertMaps(const psArray *maps // Array of maps to invert
    );


/************************************************************************************************************/

// stacRejection.c

// Transform the rejection masks back to the source frame
psArray *stacRejection(psArray *inputs,	// Input images
		       psArray *transformed, // Transformed images
		       psImage *combined, // Combined image
		       psArray *maps,	// Maps from input to transformed image
		       psArray *rejected, // Rejected images
		       stacConfig *config // Configuration
    );


#endif
