# include "ppSim.h"

bool ppSimPhotomReadoutFake(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 (!psphotAddPhotcode (recipe, config, view, "PPSIM.FAKE.CHIP")) {
        psError (PSPHOT_ERR_CONFIG, false, "trouble defining the photcode");
        return false;
    }
# endif

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

    // find the currently selected readout. 
    // we always perform photometry on the mosaiced chip
    pmReadout  *readout = pmFPAfileThisReadout (config->files, view, "PPSIM.FAKE.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);

    // the newly injected fake sources are saved on the PPSIM.OUTPUT pmFPAfile
    psArray *injectedSources = ppSimSelectSources (config, view, "PPSIM.OUTPUT");
    PS_ASSERT_PTR_NON_NULL (injectedSources, false);

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

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

    // make a copy of the injected fake-source parameters so these can be saved independently
    // from the measured fake-source parameters
    psArray *fakeSources = psArrayAlloc (injectedSources->n);
    for (int i = 0; i < injectedSources->n; i++) {
      fakeSources->data[i] = pmSourceCopy (injectedSources->data[i]);
    }

    // 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 (!psphotModelBackground (config, view, "PPSIM.FAKE.CHIP")) {
        return psphotReadoutCleanup (config, readout, recipe, NULL, NULL, NULL);
    }
    if (!psphotSubtractBackground (config, view, "PPSIM.FAKE.CHIP")) {
        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
    psMaskType maskVal = 0xff; 
    psImage *significance = psphotSignificanceImage (readout, recipe, 1, maskVal);
    ppSimDetections (significance, recipe, fakeSources);
    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, fakeSources, psf);
    
    // linear fit to real + fake sources
    psArray *sources = ppSimMergeSources (realSources, fakeSources);
    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, view, fakeSources, recipe, psf);

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

    // create the exported-metadata and free local data
    // XXX this places the sources on readout->analysis as PSPHOT.SOURCES.  modify?
    // (or don't supply the sources, and do this with a different function)
    psphotReadoutCleanup(config, readout, recipe, NULL, psf, NULL);

    pmCell    *fakeCell    = pmFPAfileThisCell (config->files, view, "PPSIM.FAKE.SOURCES"); psAssert (fakeCell, "no cell?");
    pmChip    *fakeChip    = pmFPAfileThisChip (config->files, view, "PPSIM.FAKE.SOURCES"); psAssert (fakeChip, "no chip?");
    pmReadout *fakeReadout = pmFPAfileThisReadout (config->files, view, "PPSIM.FAKE.SOURCES");
    if (!fakeReadout) {
	fakeReadout = pmReadoutAlloc (fakeCell);
	psFree (fakeReadout); // there is a copy on 'cell' as well
    }
    psAssert (fakeReadout, "no fakeReadout?");
    pmChipSetDataStatus (fakeChip, true);
    psMetadataAddArray (fakeReadout->analysis, PS_LIST_TAIL, "PSPHOT.SOURCES", PS_META_REPLACE, "fake photometry ", fakeSources);

    return true;
}
