#ifndef PP_MERGE_H
#define PP_MERGE_H

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

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <pslib.h>
#include <psmodules.h>
#include <ppStats.h>

#define TIMERNAME "ppMerge"             // Name for timer
#define PPMERGE_RECIPE "PPMERGE"        // Recipe name
#define THREADED 0

// Type of frame to merge
typedef enum {
    PPMERGE_TYPE_UNKNOWN,               // Unknown type
    PPMERGE_TYPE_BIAS,                  // Bias frame
    PPMERGE_TYPE_DARK,                  // (Multi-)Dark frame
    PPMERGE_TYPE_MASK,                  // Mask frame
    PPMERGE_TYPE_SHUTTER,               // Shutter frame
    PPMERGE_TYPE_FLAT,                  // Flat-field frame (dome or sky)
    PPMERGE_TYPE_FRINGE,                // Fringe frame
} ppMergeType;

// Files, for activation
typedef enum {
    PPMERGE_FILES_ALL,                  // All files
    PPMERGE_FILES_INPUT,                // Input files
    PPMERGE_FILES_OUTPUT                // Output files
} ppMergeFiles;

typedef struct {
    psArray *readouts;
    bool read;
    bool busy;
} ppMergeFileGroup;

// Parse command-line arguments and recipe
bool ppMergeArguments(int argc, char *argv[], // Command-line arguments
                      pmConfig *config  // Configuration
    );

// Set up camera files
bool ppMergeCamera(pmConfig *config     // Configuration
    );

// Measure scale and zero-points
bool ppMergeScaleZero(pmConfig *config  // Configuration
    );

// Main loop to do the merging
bool ppMergeLoop(pmConfig *config       // Configuration
    );

// Main loop for masks
bool ppMergeMask(pmConfig *config       // Configuration
    );

// Read nominated input file
bool ppMergeFileReadInput(pmConfig *config, // Configuration
                          pmReadout *readout, // Readout into which to read
                          int num,      // Number of file in sequence
                          int rows      // Number of rows to read at once
    );

// Open nominated input file
bool ppMergeFileOpenInput(pmConfig *config, // Configuration
                          const pmFPAview *view, // View to open
                          int num       // Number of file in sequence
    );

// Set the data level for files specified by name; return an array of the files
psArray *ppMergeFileDataLevel(const pmConfig *config, // Configuration
                              const char *name, // Name of files
                              pmFPALevel level // Level for file data level
    );

// Activate/deactivate a list of files
bool ppMergeFileActivate(const pmConfig *config, // Configuration
                         ppMergeFiles files, // Files to turn on/off
                         bool state     // Activation state
    );

// Activate/deactivate a single element for a list; return array of files
psArray *ppMergeFileActivateSingle(const pmConfig *config, // Configuration
                                   ppMergeFiles files, // Files to turn on/off
                                   bool state,   // Activation state
                                   int num // Number of file in sequence
    );

// Return name of output pmFPAfile
psString ppMergeOutputFile(const pmConfig *config // Configuration
    );


ppMergeFileGroup *ppMergeFileGroupAlloc();
ppMergeFileGroup *ppMergeReadChunk (psArray *fileGroups, pmConfig *config, int numChunk);
void *ppMergeThreadLauncher (void *data);

#endif
