# include "psphotInternal.h"

// in this psphotReadout-variant, we are only measuring the photometry for known sources,
// using a PSF generated from this observation those sources
bool psphotReadoutKnownSources(pmConfig *config, const pmFPAview *view, psArray *inSources) {

    psTimerStart ("psphotReadout");

    // select the current recipe
    psMetadata *recipe = psMetadataLookupPtr (NULL, config->recipes, PSPHOT_RECIPE);
    if (!recipe) {
        psError(PSPHOT_ERR_CONFIG, false, "missing recipe %s", PSPHOT_RECIPE);
        return false;
    }

    // set the photcode for this image
    if (!psphotAddPhotcode(recipe, config, view, "PSPHOT.INPUT")) {
        psError(PSPHOT_ERR_CONFIG, false, "trouble defining the photcode");
        return false;
    }

    // find the currently selected readout
    pmReadout  *readout = pmFPAfileThisReadout (config->files, view, "PSPHOT.INPUT");
    PS_ASSERT_PTR_NON_NULL (readout, false);

    // Generate the mask and weight images, including the user-defined analysis region of interest
    psphotSetMaskAndVariance (config, readout, recipe);

    // display the image, weight, mask (ch 1,2,3)
    psphotVisualShowImage (readout);

    // Note that in this implementation, we do NOT model the background and we do not
    // attempt to detect the sources in the image

    // include externally-supplied sources (supplied as PSPHOT.INPUT.CMF)
    pmDetections *detections = psphotDetectionsFromSources (config, inSources);
    if (!detections || !detections->peaks) {
        psError(PSPHOT_ERR_ARGUMENTS, true, "Can't find PSF stars");
        return psphotReadoutCleanup(config, readout, recipe, detections, NULL, NULL);
    }

    // construct sources and measure basic stats
    psArray *sources = psphotSourceStats (config, readout, detections, true);
    if (!sources) return false;

    // peak flux is wrong : set based on previous image
    // use the peak measured in the moments analysis:
    for (int i = 0; i < sources->n; i++) {
        pmSource *source = sources->data[i];
        source->peak->flux = source->moments->Peak;
    }

    // classify sources based on moments, brightness (psf is not known)
    if (!psphotRoughClass (readout, sources, recipe, false)) {
        psLogMsg ("psphot", 3, "failed to find a valid PSF clump for image");
        return psphotReadoutCleanup (config, readout, recipe, detections, NULL, sources);
    }

    pmPSF *psf = psphotChoosePSF (readout, sources, recipe);
    if (!psf) {
        psLogMsg ("psphot", 3, "failure to construct a psf model");
        return psphotReadoutCleanup (config, readout, recipe, detections, psf, sources);
    }
    psphotVisualShowPSFModel (readout, psf);

    // construct an initial model for each object
    psphotGuessModels (config, readout, sources, psf);

    // linear PSF fit to source peaks
    psphotFitSourcesLinear (readout, sources, recipe, psf, FALSE);

    // We have to place these visualizations here because the models are not realized until
    // psphotGuessModels or fitted until psphotFitSourcesLinear.
    psphotVisualShowPSFStars (recipe, psf, sources);
    psphotVisualShowSatStars (recipe, psf, sources);

    // measure aperture photometry corrections
    if (!psphotApResid (config, readout, sources, psf)) {
        psLogMsg ("psphot", 3, "failed on psphotApResid");
        return psphotReadoutCleanup (config, readout, recipe, detections, psf, sources);
    }

    // calculate source magnitudes
    psphotMagnitudes(config, readout, view, sources, psf);

    // drop the references to the image pixels held by each source
    psphotSourceFreePixels (sources);

    // create the exported-metadata and free local data
    return psphotReadoutCleanup(config, readout, recipe, detections, psf, sources);
}
