# include "psastroInternal.h"
# define ELIXIR_MODE 1

psArray *psastroLoadRefstars (pmConfig *config) {

    int fd;
    bool status;

    // select the current recipe
    psMetadata *recipe  = psMetadataLookupPtr (NULL, config->recipes, PSASTRO_RECIPE);

    // DVO APIs expect decimal degrees
    float RAmin  = DEG_RAD*psMetadataLookupF32(NULL, recipe, "RA_MIN");
    float RAmax  = DEG_RAD*psMetadataLookupF32(NULL, recipe, "RA_MAX");
    float DECmin = DEG_RAD*psMetadataLookupF32(NULL, recipe, "DEC_MIN");
    float DECmax = DEG_RAD*psMetadataLookupF32(NULL, recipe, "DEC_MAX");
    // float MAGmax = psMetadataLookupF32(NULL, recipe, "MAG_MAX");

    // XXX CATDIR needs to look up abstracted name from psastro.config
    // XXX which is then selected from the top-level ipprc.config
    char *catdir = psMetadataLookupStr(NULL, recipe, "DVO.CATDIR");
    psString CATDIR = pmConfigConvertFilename(catdir, config, false); // Resolved filename
    PS_ASSERT (CATDIR, NULL);

    char *getstarCommand = psMemIncrRefCounter(psMetadataLookupStr(NULL, recipe, "DVO.GETSTAR"));
    PS_ASSERT (getstarCommand, NULL);

    // issue the following command:
    // getstar -region RAmin RAmax DECmin DECmax
    char tempFile[64];
    sprintf (tempFile, "/tmp/psastro.XXXXXX");
    if ((fd = mkstemp (tempFile)) == -1) {
        psError(PSASTRO_ERR_REFSTARS, true, "error creating temp output file\n");
        psFree(CATDIR);
        return NULL;
    }
    close (fd);

    psTimerStart ("psastro");

    // use fork to add timeout capability
    if (ELIXIR_MODE) {
        psStringAppend (&getstarCommand, " -D CATFORMAT elixir");
    } else {
        psStringAppend (&getstarCommand, " -D CATFORMAT panstarrs");
    }

    // check for default name (use .ptolemyrc), or use specified CATDIR
    if (strcasecmp(CATDIR, "NONE")) {
        psStringAppend (&getstarCommand, " -D CATDIR %s", CATDIR);
    }
    psFree(CATDIR);

    // psStringAppend (&getstarCommand, " -D CATMODE mef -maglim %f -region %f %f %f %f -o %s", MAGmax, RAmin, DECmin, RAmax, DECmax, tempFile);
    // XXX TEST : no magnitude limit
    psStringAppend (&getstarCommand, " -D CATMODE mef -region %f %f %f %f -o %s", RAmin, DECmin, RAmax, DECmax, tempFile);
    psTrace ("psastro", 3, "%s\n", getstarCommand);

    // XXX use psPipe: catch stderr, stdout, allow for Nsec timeout...
    status = system (getstarCommand);
    if (status) {
        psError(PSASTRO_ERR_REFSTARS, true, "error loading reference data\n");
        return NULL;
    }
    psFree (getstarCommand);

    psLogMsg ("psastro", 3, "ran getstar : %f sec\n", psTimerMark ("psastro"));

    // the output from getstar is a file with the Average table
    psFits *fits = psFitsOpen (tempFile, "r");

    if (ELIXIR_MODE) {
        psFitsMoveExtName (fits, "DVO_AVERAGE_ELIXIR");
    } else {
        psFitsMoveExtName (fits, "DVO_AVERAGE_PANSTARRS");
    }

    psTimerStart ("psastro");
    psMetadata *header = psFitsReadHeader (NULL, fits);
    psArray *table = psFitsReadTable (fits);
    psFitsClose (fits);

    unlink (tempFile);

    if (table == NULL) {
        psError(PSASTRO_ERR_REFSTARS, true, "failure to load astrometric reference\n");
        return NULL;
    }

    psLogMsg ("psastro", 3, "read getstar output table : %f sec\n", psTimerMark ("psastro"));

    // convert the Average table to the pmAstromObj entries
    psTimerStart ("psastro");

    psArray *refstars = psArrayAllocEmpty (table->n);
    for (int i = 0; i < table->n; i++) {
        pmAstromObj *ref = pmAstromObjAlloc ();

        psMetadata *row = table->data[i];

        // DVO tables are stored in degrees
        if (ELIXIR_MODE) {
            ref->sky->r   = RAD_DEG*psMetadataLookupF32 (&status, row, "RA");
            ref->sky->d   = RAD_DEG*psMetadataLookupF32 (&status, row, "DEC");
            ref->Mag      = 0.001*psMetadataLookupS32 (&status, row, "MAG");  // ELIXIR uses millimags
        } else {
            ref->sky->r   = RAD_DEG*psMetadataLookupF64 (&status, row, "RA");
            ref->sky->d   = RAD_DEG*psMetadataLookupF64 (&status, row, "DEC");
            ref->Mag      = psMetadataLookupF32 (&status, row, "MAG"); // PANSTARRS uses mags
        }

        psArrayAdd (refstars, 100, ref);
        psFree (ref);
    }
    psFree (header);
    psFree (table);
    psLogMsg ("psastro", 3, "converted table to pmAstromObj : %f sec\n", psTimerMark ("psastro"));

    psTrace ("psastro", 3, "loaded %ld reference stars from (%10.6f,%10.6f) - (%10.6f,%10.6f)\n",
             refstars->n, RAmin, DECmin, RAmax, DECmax);

    // dump or plot the available refstars
    if (psTraceGetLevel("psastro.dump") > 0) {
        psastroDumpRefstars (refstars, "refstars.dat");
    }

    if (psTraceGetLevel("psastro.plot") > 0) {
        psastroPlotRefstars (refstars);
    }

    return refstars;
}
