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

#include <stdio.h>
#include <pslib.h>
#include <psmodules.h>
#include <psphot.h>

#include "ppStack.h"
#include "ppStackLoop.h"

bool ppStackPhotometry(ppStackOptions *options, pmConfig *config)
{
    psAssert(options, "Require options");
    psAssert(config, "Require configuration");

    psMetadata *recipe = psMetadataLookupMetadata(NULL, config->recipes, PPSTACK_RECIPE); // ppStack recipe
    psAssert(recipe, "We've thrown an error on this before.");

    bool mdok;                          // Status of MD lookup
    if (!psMetadataLookupBool(&mdok, recipe, "PHOTOMETRY")) {
        // Nothing to do
        return true;
    }

    psTimerStart("PPSTACK_PHOT");

    ppStackFileActivation(config, PPSTACK_FILES_COMBINE, false);
    ppStackFileActivation(config, PPSTACK_FILES_PHOT, true);
    pmFPAview *photView = ppStackFilesIterateDown(config); // View to readout
    ppStackFileActivation(config, PPSTACK_FILES_COMBINE, true);

    pmFPAfile *photFile = psMetadataLookupPtr(NULL, config->files, "PSPHOT.INPUT"); // File for photometry
    pmFPACopy(photFile->fpa, options->outRO->parent->parent->parent);

    if (psMetadataLookupBool(NULL, config->arguments, "-visual")) {
        pmVisualSetVisual(true);
    }

    psMetadata *psphot = psMetadataLookupMetadata(NULL, config->recipes, PSPHOT_RECIPE); // Recipe

#if 0
    // Need to ensure aperture residual is not calculated
    psMetadataItem *item = psMetadataLookup(recipe, "MEASURE.APTREND"); // Item determining aptrend
    if (!item) {
        psWarning("Unable to find MEASURE.APTREND in psphot recipe");
        psErrorClear();
    } else {
        item->data.B = false;
    }
#endif

    // set maskValue and markValue in the psphot recipe
    psImageMaskType maskValue = pmConfigMaskGet("BLANK", config); // Bits to mask
    psImageMaskType markValue = pmConfigMaskGet("MARK.VALUE", config); // Bits to use for marking
    psMetadataAddImageMask(psphot, PS_LIST_TAIL, "MASK.PSPHOT", PS_META_REPLACE,
                            "Bits to mask", maskValue);
    psMetadataAddImageMask(psphot, PS_LIST_TAIL, "MARK.PSPHOT", PS_META_REPLACE,
                           "Bits to use for mark", markValue);

    pmCell *sourcesCell = pmFPAfileThisCell(config->files, photView, "PPSTACK.OUTPUT");
    psArray *inSources = psMetadataLookupPtr(NULL, sourcesCell->analysis, "PSPHOT.SOURCES");
    if (!inSources) {
        psError(PS_ERR_UNKNOWN, false, "Unable to find input sources");
        psFree(photView);
        return false;
    }

    if (!psphotReadoutKnownSources(config, photView, inSources)) {
        // This is likely a data quality issue
        // XXX Split into multiple cases using error codes?
        psErrorStackPrint(stderr, "Unable to perform photometry on image");
        psWarning("Unable to perform photometry on image --- suspect bad data quality.");
        if (options->stats && psMetadataLookupS32(NULL, options->stats, "QUALITY") == 0) {
            psMetadataAddS32(options->stats, PS_LIST_TAIL, "QUALITY", PS_META_REPLACE,
                             "Unable to perform photometry on image", psErrorCodeLast());
        }
        psErrorClear();
        psphotFilesActivate(config, false);
    }

    if (!pmFPAfileDropInternal(config->files, "PSPHOT.BACKMDL") ||
        !pmFPAfileDropInternal (config->files, "PSPHOT.BACKMDL.STDEV") ||
        !pmFPAfileDropInternal (config->files, "PSPHOT.BACKGND")) {
        psError(PS_ERR_UNKNOWN, false, "Unable to drop PSPHOT internal files.");
        return false;
    }

    pmFPAfileActivate(config->files, false, "PSPHOT.INPUT");

    if (options->stats) {
        pmReadout *photRO = pmFPAviewThisReadout(photView, photFile->fpa); // Readout with the sources
        psArray *sources = psMetadataLookupPtr(NULL, photRO->analysis, "PSPHOT.SOURCES"); // Sources
        psMetadataAddS32(options->stats, PS_LIST_TAIL, "NUM_SOURCES", 0,
                         "Number of sources detected", sources ? sources->n : 0);
        psMetadataAddF32(options->stats, PS_LIST_TAIL, "TIME_PHOT", 0,
                         "Time to do photometry", psTimerMark("PPSTACK_PHOT"));
    }
    psFree(photView);

    psLogMsg("ppStack", PS_LOG_INFO, "Time to do photometry: %f sec", psTimerClear("PPSTACK_PHOT"));

    return true;
}
