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

/*
 * shiftSize:
 * A stripped-down version of STAC that outputs the necessary size to keep all the pixels in the individual
 * images within the shifted images.
 *
 */

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <getopt.h>
#include <string.h>
#include "pslib.h"
#include "stac.h"

void help(const char *name)
{
    fprintf (stderr, "shiftSize: Calculate size for output combined image\n"
             "Usage: %s [-h] [-v] IN1 IN2...\n"
             "where\n"
             "\t-h           Help (this info)\n"
             "\t-v           Increase verbosity level\n"
             "\tIN1, IN2...  Input images, which have associated .map files.\n",
             name
        );
}

int main(int argc, char *argv[])
{
    // Set trace levels
    (void)psTraceSetLevel(".",0);
    (void)psTraceSetLevel("err", 10);
#ifdef TESTING
    (void)psTraceSetLevel("stac.checkMemory",10);
    (void)psTraceSetLevel("stac.read",10);
    (void)psTraceSetLevel("stac.size",10);
#endif

    // Set logging level
    psLogSetLevel(9);


    int verbose = 0;                    // Verbosity level

    // Parse command line
    const char *programName = argv[0];  // Program name
    /* Variables for getopt */
    int opt;   /* Option, from getopt */
    extern char *optarg;   /* Argument accompanying switch */
    extern int optind;   /* getopt variables */

    /* Parse command-line arguments using getopt */
    while ((opt = getopt(argc, argv, "hv")) != -1) {
        switch (opt) {
          case 'h':
            help(programName);
            exit(EXIT_SUCCESS);
          case 'v':
            verbose++;
            break;
          default:
            help(programName);
        }
    }

    /* Get the remaining, mandatory values */
    argc -= optind;
    argv += optind;
    if (argc < 1) {
        help(programName);
        exit(EXIT_FAILURE);
    }

    psArray *inputs = psArrayAlloc(argc); // Input filenames
    for (int i = 0; i < argc; i++) {
        inputs->data[i] = psStringCopy(argv[i]);
        psTrace("stac.size", 8, "Input file: %s\n", (char*)inputs->data[i]);
    }

    // Read input files
    psVector *xSize = psVectorAlloc(inputs->n, PS_TYPE_S32);
    psVector *ySize = psVectorAlloc(inputs->n, PS_TYPE_S32);
    for (int i = 0; i < inputs->n; i++) {
        const char *filename = inputs->data[i]; // Name of FITS file
        psFits *file = psFitsOpen(filename, "r"); // FITS file handle
        psMetadata *header = psFitsReadHeader(NULL, file); // FITS header
        psFitsClose(file);
        bool mdok = true;               // Status of MD lookup
        xSize->data.S32[i] = psMetadataLookupS32(&mdok, header, "NAXIS1");
        if (!mdok) {
            psError(PS_ERR_IO, true, "Unable to find NAXIS1 in %s\n", filename);
            exit(EXIT_FAILURE);
        }
        ySize->data.S32[i] = psMetadataLookupS32(&mdok, header, "NAXIS2");
        if (!mdok) {
            psError(PS_ERR_IO, true, "Unable to find NAXIS2 in %s\n", filename);
            exit(EXIT_FAILURE);
        }
        psFree(header);
    }

    // Read maps
    psArray *maps = stacReadMaps(inputs);

    // Get size
    int outnx, outny;                   // Size of combined image
    float xMapDiff, yMapDiff;           // Difference to apply to maps
    stacSize(&outnx, &outny, &xMapDiff, &yMapDiff, xSize, ySize, maps);
    psFree(xSize);
    psFree(ySize);

    printf("%d %d\n", outnx, outny);

    // Write out altered maps
    stacWriteMaps(inputs, maps);

    psFree(inputs);
    psFree(maps);

#ifdef TESTING
    // Check memory for leaks, corruption
    stacCheckMemory();
#endif

}
