# include "ppSim.h"

bool ppSimPhotomReadoutForce(pmConfig *config, const pmFPAview *view) {

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

# if 0
    // set the photcode for this image
    if (!psphotAddPhotcodeReadout (recipe, config, view, "PPSIM.FAKE.CHIP", 0)) {
        psError (PSPHOT_ERR_CONFIG, false, "trouble defining the photcode");
        return false;
    }
# endif

    // *** in this section, perform the photometry for real + force sources on PPSIM.FORCE.CHIP ***

    // find the currently selected readout.
    // we always perform photometry on the mosaiced chip
    pmReadout  *readout = pmFPAfileThisReadout (config->files, view, "PPSIM.FORCE.CHIP");
    PS_ASSERT_PTR_NON_NULL (readout, false);

    // the previously measured real sources are loaded into the PPSIM.REAL.SOURCES pmFPAfile
    psArray *realMeasuredSources = ppSimSelectSources (config, view, "PPSIM.REAL.SOURCES");
    PS_ASSERT_PTR_NON_NULL (realMeasuredSources, false);

    // load the forced source lists
    psArray *forceSources = ppSimLoadForceSources (config, view);
    psAssert (forceSources, "failed to load force photometry sources");

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

    // XXX need to define the source pixels
    ppSimDefinePixels (realMeasuredSources, readout, recipe);
    ppSimDefinePixels (forceSources, readout, recipe);

    // make a copy of the measured real-source parameters so these can be fitted here and in
    // ppSimPhotomReadoutForce, if desired.
    psArray *realSources = psArrayAlloc (realMeasuredSources->n);
    for (int i = 0; i < realMeasuredSources->n; i++) {
        realSources->data[i] = pmSourceCopy (realMeasuredSources->data[i]);
    }

    // load the psf model, if suppled.  FWHM_X,FWHM_Y,etc are saved in the recipe
    // this function uses PSPHOT.PSF.LOAD as the pmFPAfile
    pmPSF *psf = psphotLoadPSF (config, view, recipe);
    assert (psf);

    // remove all sources
    psphotRemoveAllSources (realSources, recipe);

    // generate a background model (median, smoothed image)
    if (!psphotModelBackgroundReadoutFileIndex (config, view, "PPSIM.FORCE.CHIP", 0)) {
        return psphotReadoutCleanup (config, readout, recipe, NULL, NULL, NULL);
    }
    if (!psphotSubtractBackgroundReadout (config, view, "PPSIM.FORCE.CHIP", 0)) {
        return psphotReadoutCleanup (config, readout, recipe, NULL, NULL, NULL);
    }

    // add noise for real (subtracted) objects
    psphotAddNoise (readout, realSources, recipe);

    // XXX fake sources should measure peak->x,y, force sources should not
    psImageMaskType maskVal = 0xff;
    psImage *significance = psphotSignificanceImage (readout, recipe, 1, maskVal);
    ppSimDetections (significance, recipe, forceSources);
    psFree (significance);

    // remove noise for subtracted objects (ie, return to normal noise level)
    psphotSubNoise (readout, realSources, recipe);

    // replace all sources
    psphotReplaceAllSources (realSources, recipe);

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

    // linear fit to real + force sources
    psArray *sources = ppSimMergeSources (realSources, forceSources);
    psphotFitSourcesLinear (readout, sources, recipe, psf, FALSE); // XXX option to NOT subtract
    psphotReplaceAllSources (sources, recipe);
    psFree (sources); // only frees the merged references

    // calculate source magnitudes (for which set??)
    psphotMagnitudes(config, readout, view, forceSources, psf);

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

    // create the exported-metadata and free local data
    psphotReadoutCleanup(config, readout, recipe, NULL, psf, NULL);

    pmCell    *forceCell    = pmFPAfileThisCell (config->files, view, "PPSIM.FORCE.SOURCES"); psAssert (forceCell, "no cell?");
    pmChip    *forceChip    = pmFPAfileThisChip (config->files, view, "PPSIM.FORCE.SOURCES"); psAssert (forceChip, "no chip?");
    pmReadout *forceReadout = pmFPAfileThisReadout (config->files, view, "PPSIM.FORCE.SOURCES");
    if (!forceReadout) {
        forceReadout = pmReadoutAlloc (forceCell);
        psFree (forceReadout); // there is a copy on 'cell' as well
    }
    psAssert (forceReadout, "no forceReadout?");
    pmChipSetDataStatus (forceChip, true);

    pmDetections *detections = pmDetectionsAlloc();
    detection->allSources = forceSources;
    psMetadataAddArray (forceReadout->analysis, PS_LIST_TAIL, "PSPHOT.DETECTIONS", PS_META_REPLACE, "force photometry ", detections);
    psFree(detections);

    return true;
}
