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

#include <stdio.h>
#include <pslib.h>
#include <psmodules.h>

#include "ppMerge.h"
#include "ppMergeConfig.h"

#define DONT_USE_DB

// Output usage information
static void usage(const char *programName, // Name of the program
                  pmConfig *config      // Configuration (contains the arguments list)
    )
{
    printf("Merge multiple calibration frames into a master frame by stacking.\n\n"
           "Usage:\n"
           "\t%s OUTPUT.fits INPUT1.fits INPUT2.fits ...\n"
           "\n", programName);
    psArgumentHelp(config->arguments);
    exit(EXIT_FAILURE);
}

pmConfig *ppMergeConfig(int argc, char **argv)
{
    pmConfig *config = pmConfigRead(&argc, argv, PPMERGE_RECIPE);
    // Load the site-wide configuration information
    if (! config) {
        psErrorStackPrint(stderr, "Can't find site configuration!\n");
        exit(EXIT_FAILURE);
    }

    // Command-line arguments
    psMetadataAddStr(config->arguments, PS_LIST_TAIL, "-type", 0, "Type of calibration frame", "");
    psMetadataAddBool(config->arguments, PS_LIST_TAIL, "-zero", 0, "Subtract background?", false);
    psMetadataAddBool(config->arguments, PS_LIST_TAIL, "-scale", 0, "Scale by background?", false);
    psMetadataAddBool(config->arguments, PS_LIST_TAIL, "-exptime", 0, "Scale by the exposure time?", false);
    psMetadataAddS32(config->arguments, PS_LIST_TAIL, "-onoff", 0, "Number of on/off pairs", 0);
    psMetadataAddStr(config->arguments, PS_LIST_TAIL, "-stats", 0, "MDC file to hold statistics ", NULL);

    if (argc == 1) {
        usage(argv[0], config);
    }

    // Parse the arguments
    if (! psArgumentParse(config->arguments, &argc, argv) || argc < 3) {
        usage(argv[0], config);
    }

    // Add the output image to the arguments list
    psMetadataAddStr(config->arguments, PS_LIST_TAIL, "OUTPUT", 0, "Name of the output image",
                     argv[1]);

    // Everything remaining must be input files
    if (argc - 2 <= 1) {
        psErrorStackPrint(stderr, "No files to combine.\n");
        exit(EXIT_FAILURE);
    }
    psArray *files = psArrayAlloc(argc - 2);
    for (int i = 2; i < argc; i++) {
        files->data[i - 2] = psStringCopy(argv[i]);
    }
    psMetadataAddPtr(config->arguments, PS_LIST_TAIL, "INPUT", PS_DATA_ARRAY,
                     "Array of inputs images", files);
    psFree(files);                      // Drop reference

#ifndef DONT_USE_DB
#ifdef HAVE_PSDB
    // Define database handle, if required
    config->database = pmConfigDB(config);
#endif
#endif

    // Add concepts for scale and zero
    psMetadataItem *scaleItem = psMetadataItemAllocF32("PPMERGE.SCALE", "Scaling for ppMerge", NAN);
    psMetadataItem *zeroItem = psMetadataItemAllocF32("PPMERGE.ZERO", "Zero offset for ppMerge", NAN);
    pmConceptRegister(scaleItem, NULL, NULL, false, PM_FPA_LEVEL_CELL);
    pmConceptRegister(zeroItem, NULL, NULL, false, PM_FPA_LEVEL_CELL);
    psFree(scaleItem);
    psFree(zeroItem);

    return config;
}
