# include "psphotStandAlone.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;
    }

    if ((N = psArgumentGet (argc, argv, "-version"))) {
        psString version;
        version = psphotVersionLong();    fprintf (stdout, "%s\n", version); psFree (version);
        version = psModulesVersionLong(); fprintf (stdout, "%s\n", version); psFree (version);
        version = psLibVersionLong();     fprintf (stdout, "%s\n", version); psFree (version);
        exit (0);
    }

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

    // save the following additional recipe values based on command-line options
    // these options override the PSPHOT recipe values loaded from recipe files
    psMetadata *options = pmConfigRecipeOptions (config, PSPHOT_RECIPE);

    // Number of threads
    if ((N = psArgumentGet(argc, argv, "-threads"))) {
        psArgumentRemove(N, &argc, argv);
        int nThreads = atoi(argv[N]);
        psMetadataAddS32(config->arguments, PS_LIST_TAIL, "NTHREADS", 0, "number of psphot threads", nThreads);
        psArgumentRemove(N, &argc, argv);

        // create the thread pool with number of desired threads, supplying our thread launcher function
        psThreadPoolInit (nThreads);
    }
    psphotSetThreads();

    // 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);
    }

    // visual : interactive display mode
    if ((N = psArgumentGet (argc, argv, "-visual"))) {
        psArgumentRemove (N, &argc, argv);
        pmVisualSetVisual(true);
    }

    // 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);
    }

    // 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, "", argv[N]);
        psArgumentRemove (N, &argc, argv);
    }

    // if these command-line options are supplied, load the file name lists into config->arguments
    // override any configuration-specified source for these files
    //
    pmConfigFileSetsMD (config->arguments, &argc, argv, "MASK",   "-mask",   "-masklist");
    pmConfigFileSetsMD (config->arguments, &argc, argv, "VARIANCE", "-variance", "-variancelist");
    pmConfigFileSetsMD (config->arguments, &argc, argv, "PSPHOT.PSF", "-psf", "-psflist");
    pmConfigFileSetsMD (config->arguments, &argc, argv, "SRC",    "-src",    "-srclist");

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

    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("psphot", 1, "Done with psphotArguments...\n");
    return (config);
}
