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

# include "psphot.h"
# include <glob.h>

pmConfig *psphotArguments(int argc, char **argv) {

    int N;
    bool status;

    if (argc == 1) {
        psError(PSPHOT_ERR_ARGUMENTS, true, "Too few arguments: %d", argc);
        return NULL;
    }

    // load config data from default locations
    pmConfig *config = pmConfigRead(&argc, argv);
    if (config == NULL) {
        psError(PSPHOT_ERR_CONFIG, false, "Can't read site configuration");
        return NULL;
    }

    // save the recipe options separately until we have loaded the recipe (psphotParseDetrend)
    psMetadata *options = psMetadataAlloc ();
    psMetadataAddPtr (config->arguments, PS_LIST_TAIL, "PSPHOT.OPTIONS",  PS_DATA_METADATA, "", options);

    // the following options override the PSPHOT recipe options

    // run the test model (requires X,Y coordinate)
    if ((N = psArgumentGet (argc, argv, "-modeltest"))) {
        psMetadataAddBool (options, PS_LIST_TAIL, "TEST_FIT",   0, "", true);
        psMetadataAddF32  (options, PS_LIST_TAIL, "TEST_FIT_X", 0, "", atof(argv[N+1]));
        psMetadataAddF32  (options, PS_LIST_TAIL, "TEST_FIT_Y", 0, "", atof(argv[N+2]));

        psArgumentRemove (N, &argc, argv);
        psArgumentRemove (N, &argc, argv);
        psArgumentRemove (N, &argc, argv);

        // specify the modeltest model
        if ((N = psArgumentGet (argc, argv, "-model"))) {
            psArgumentRemove (N, &argc, argv);
            psMetadataAddStr (options, PS_LIST_TAIL, "TEST_FIT_MODEL", 0, "", argv[N]);
            psArgumentRemove (N, &argc, argv);
        }

        // specify the test fit mode
        if ((N = psArgumentGet (argc, argv, "-fitmode"))) {
            psArgumentRemove (N, &argc, argv);
            psMetadataAddStr (options, PS_LIST_TAIL, "TEST_FIT_MODE", 0, "", argv[N]);
            psArgumentRemove (N, &argc, argv);
        }
        if ((N = psArgumentGet (argc, argv, "-fitset"))) {
            psArgumentRemove (N, &argc, argv);
            psMetadataAddStr (options, PS_LIST_TAIL, "TEST_FIT_SET", 0, "", argv[N]);
            psArgumentRemove (N, &argc, argv);
        }
    }

    // photcode : used in output to supplement header data (argument or recipe?)
    if ((N = psArgumentGet (argc, argv, "-photcode"))) {
        psArgumentRemove (N, &argc, argv);
        psMetadataAddStr (options, PS_LIST_TAIL, "PHOTCODE", PS_META_REPLACE, "", argv[N]);
        psArgumentRemove (N, &argc, argv);
    }

    // break : used from recipe throughout psphotReadout
    if ((N = psArgumentGet (argc, argv, "-break"))) {
        psArgumentRemove (N, &argc, argv);
        psMetadataAddStr (options, PS_LIST_TAIL, "BREAK_POINT", PS_META_REPLACE, "", argv[N]);
        psArgumentRemove (N, &argc, argv);
    }

    // fitmode : used from recipe throughout psphotReadout
    if ((N = psArgumentGet (argc, argv, "-fitmode"))) {
        psArgumentRemove (N, &argc, argv);
        psMetadataAddStr (options, PS_LIST_TAIL, "FITMODE", PS_META_REPLACE, "", argv[N]);
        psArgumentRemove (N, &argc, argv);
    }

    // analysis region : overrides recipe value, used in psphotReadout/psphotEnsemblePSF
    if ((N = psArgumentGet (argc, argv, "-region"))) {
        psArgumentRemove (N, &argc, argv);
        psMetadataAddStr (options, PS_LIST_TAIL, "ANALYSIS_REGION", 0, "", argv[N]);
        psArgumentRemove (N, &argc, argv);
    }

    // other arbitrary recipe values: -D key value (all added as string)
    while ((N = psArgumentGet (argc, argv, "-D"))) {
        psArgumentRemove (N, &argc, argv);
        psMetadataAddStr (options, PS_LIST_TAIL, argv[N], 0, "", argv[N+1]);
        psArgumentRemove (N, &argc, argv);
        psArgumentRemove (N, &argc, argv);
    }

    // other arbitrary recipe values: -Df key value (all added as float)
    while ((N = psArgumentGet (argc, argv, "-Df"))) {
        psArgumentRemove (N, &argc, argv);
        psMetadataAddF32 (options, PS_LIST_TAIL, argv[N], 0, "", atof(argv[N+1]));
        psArgumentRemove (N, &argc, argv);
        psArgumentRemove (N, &argc, argv);
    }

    // other arbitrary recipe values: -Di key value (all added as int)
    while ((N = psArgumentGet (argc, argv, "-Di"))) {
        psArgumentRemove (N, &argc, argv);
        psMetadataAddS32 (options, PS_LIST_TAIL, argv[N], 0, "", atoi(argv[N+1]));
        psArgumentRemove (N, &argc, argv);
        psArgumentRemove (N, &argc, argv);
    }

    // drop the local view on the options (saved on config->arguments)
    psFree (options);

    // the input file is a required argument; if not found, we will exit
    status = pmConfigFileSetsMD (config->arguments, config, "INPUT", "-file", "-list");
    if (!status) {
        psError(PSPHOT_ERR_ARGUMENTS, false, "pmConfigFileSetsMD failed to parse arguments");
        return NULL;
    }

    // chip selection is used to limit chips to be processed
    if ((N = psArgumentGet (argc, argv, "-chip"))) {
        psArgumentRemove (N, &argc, argv);
        psMetadataAddStr (config->arguments, PS_LIST_TAIL, "CHIP_SELECTIONS", PS_DATA_STRING, "", psStringCopy(argv[N]));
        psArgumentRemove (N, &argc, argv);
    }

    if (argc != 2) {
        psError(PSPHOT_ERR_ARGUMENTS, true, "Expected to see one more argument; saw %d", argc - 1);
        return NULL;
    }

    // output position is fixed
    psMetadataAddStr (config->arguments, PS_LIST_TAIL, "OUTPUT", 0, "", argv[1]);

    psTrace(__func__, 1, "Done with psphotArguments...\n");
    return (config);
}
