# include "psphotInternal.h"

// this badly-named function performs photometry assuming (a) a supplied PSF, (b)
// background subtraction, (c) linear psf-model fits only.  it is currently only being
// used by ppSub.

// NOTE: ppSub needs to perform extended source analysis for comets and trails.

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

    // measure the total elapsed time in psphotReadout.  XXX the current threading plan
    // for psphot envisions threading within psphotReadout, not multiple threads calling
    // the same psphotReadout.  In the current plan, this dtime is the elapsed time used
    // jointly by the multiple threads, not the total time used by all threads.
    psTimerStart ("psphotReadout");

    pmModelClassSetLimits(PM_MODEL_LIMITS_LAX);

    // 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);

    // load the psf model, if suppled.  FWHM_X,FWHM_Y,etc are saved in the recipe
    pmPSF *psf = psphotLoadPSF (config, view, recipe);
    if (!psf) {
      psError (PSPHOT_ERR_CONFIG, false, "missing psf model");
      return psphotReadoutCleanup (config, readout, recipe, NULL, NULL, NULL);
    }

    // find the detections (by peak and/or footprint) in the image.
    pmDetections *detections = pmDetectionsAlloc(); // New detections; allocated to ensure pass=2
    detections = psphotFindDetections(detections, readout, recipe);
    if (!detections) {
        psLogMsg ("psphot", 3, "unable to find detections in this image");
        return psphotReadoutCleanup (config, readout, recipe, detections, psf, NULL);
    }

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

    // find blended neighbors of very saturated stars
    // XXX merge this with Basic Deblend?
    psphotDeblendSatstars (readout, sources, recipe);

    // mark blended peaks PS_SOURCE_BLEND
    if (!psphotBasicDeblend (sources, recipe)) {
        psLogMsg ("psphot", 3, "failed on deblend analysis");
        return psphotReadoutCleanup (config, readout, recipe, detections, psf, sources);
    }

    // classify sources based on moments, brightness (use supplied psf shape parameters)
    if (!psphotRoughClass (readout, sources, recipe, true)) {
        psLogMsg ("psphot", 3, "failed to find a valid PSF clump for image");
        return psphotReadoutCleanup (config, readout, recipe, detections, psf, sources);
    }

    // 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);

// XXX eventually, add the extended source fits here
# if (0)
    // measure source size for the remaining sources
    psphotSourceSize (config, readout, sources, recipe, 0);

    psphotExtendedSourceAnalysis (readout, sources, recipe);

    psphotExtendedSourceFits (readout, sources, recipe);
# endif

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

    if (!psphotEfficiency(config, readout, view, psf, recipe, sources)) {
        psErrorStackPrint(stderr, "Unable to determine detection efficiencies from fake sources");
        psErrorClear();
    }

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