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

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

void help(const char *programName
    )
{
    fprintf (stderr, "shift: shift an image, given the transformation\n"
             "Usage: %s [-h] [-v] [-g GAIN] [-r READNOISE] [-s SAT] [-b BAD] [-p FILE MAP] [-a APER] [-k SIGMAREJ] [-n NREJECT] OUT IN1 IN2...\n"
             "where\n"
             "\t-h           Help (this info)\n"
             "\t-v           Increase verbosity level\n"
             "\t-g GAIN      Gain in e/ADU (1.0)\n"
             "\t-r READNOISE Read noise in e (0.0)\n"
             "\t-s SAT       Saturation point (65535)\n"
             "\t-b BAD       Bad level (0)\n"
             "\t-p FILE MAP  Specify file containing star coordinates, with map\n"
             "\t-a APER      Aperture radius for photometry (3.0)\n"
             "\t-k SIGMAREJ  k-sigma rejection threshold (3.0)\n"
             "\t-n NREJECT   Number of rejection iterations (1)\n"
             "\tOUT          Output image\n"
             "\tIN1 IN2...   Input images (identical size)\n",
             programName
        );
}


combineConfig *combineConfigAlloc(void)
{
    combineConfig *config = psAlloc(sizeof(combineConfig)); // Configuration

    // Parameters with default values
    config->verbose = 0;                // Verbosity level
    config->gain = 1.0;                 // Gain (e/ADU)
    config->readnoise = 0.0;            // Read noise (e)
    config->reject = 4.0;               // Rejection threshold (sigma)
    config->nReject = 1;                // Number of rejection iterations
    config->saturated = 65535.0;        // Saturation level
    config->bad = 0.0;                  // Bad level
    config->outName = NULL;             // Output name
    config->inNames = NULL;             // Input names;
    config->starFile = NULL;            // Filename of file containing stars
    config->starMap = NULL;             // Map for stars
    config->aper = 3.0;                 // Aperture for photometry

    return config;
}

void combineConfigFree(combineConfig *config)
{
    psFree(config->inNames);
    psFree(config);
}


combineConfig *combineParseConfig(int argc, char *argv[])
{
    combineConfig *config = combineConfigAlloc(); // Configuration

    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, "hvg:r:s:b:p:a:k:n:")) != -1) {
        switch (opt) {
          case 'h':
            help(programName);
            exit(EXIT_SUCCESS);
          case 'v':
            config->verbose++;
            break;
          case 'r':
            if (sscanf(optarg, "%f", &config->readnoise) != 1) {
                printf("Unable to read readnoise.\n");
                help(programName);
                exit(EXIT_FAILURE);
            }
            break;
          case 'g':
            if (sscanf(optarg, "%f", &config->gain) != 1) {
                printf("Unable to read gain.\n");
                help(programName);
                exit(EXIT_FAILURE);
            }
            break;
          case 's':
            if (sscanf(optarg, "%f", &config->saturated) != 1) {
                printf("Unable to read saturation limit.\n");
                help(programName);
                exit(EXIT_FAILURE);
            }
            break;
          case 'b':
            if (sscanf(optarg, "%f", &config->bad) != 1) {
                printf("Unable to read bad limit.\n");
                help(programName);
                exit(EXIT_FAILURE);
            }
            break;
          case 'p':
            if (argc < optind+1) {
                printf("Unable to read photometric files.\n");
                help(programName);
                exit(EXIT_FAILURE);
            }
            config->starFile = argv[optind-1];
            config->starMap = argv[optind++];
            // Note: incrementing optind, so I can read more than one parameter.
            break;
          case 'a':
            if (sscanf(optarg, "%f", &config->aper) != 1) {
                printf("Unable to read aperture.\n");
                help(programName);
                exit(EXIT_FAILURE);
            }
            break;
          case 'k':
            if (sscanf(optarg, "%f", &config->reject) != 1) {
                printf("Unable to read rejection limit.\n");
                help(programName);
                exit(EXIT_FAILURE);
            }
            break;
          case 'n':
            if (sscanf(optarg, "%d", &config->nReject) != 1) {
                printf("Unable to read number of rejection iterations.\n");
                help(programName);
                exit(EXIT_FAILURE);
            }
            break;
          default:
            printf("Bad option: %c\n", opt);
            help(programName);
            exit(EXIT_FAILURE);
        }
    }

    /* Get the remaining, mandatory values */
    argc -= optind;
    argv += optind;
    if (argc < 2) {
        help(programName);
        exit(EXIT_FAILURE);
    }
    config->outName = argv[0];          // Output filename
    config->inNames = psArrayAlloc(argc-1); // Input filenames
    for (int i = 1; i < argc; i++) {
        config->inNames->data[i-1] = psAlloc(strlen(argv[i]));
        strncpy(config->inNames->data[i-1], argv[i], strlen(argv[i]));
    }

    return config;
}
