# include "psphotInternal.h"

// smooth the image, search for peaks, optionally define footprints based on the peaks
pmDetections *psphotFindDetections (pmDetections *detections, pmReadout *readout, psMetadata *recipe) {

    bool status;
    int pass;
    float NSIGMA_PEAK = 25.0;
    int NMAX = 0;

    psTimerStart ("psphot");

    // user-defined masks to test for good/bad pixels (build from recipe list if not yet set)
    psMaskType maskVal = psMetadataLookupU8(&status, recipe, "MASK.PSPHOT"); // Mask value for bad pixels
    assert (maskVal);

    // Use the new pmFootprints approach?
    const bool useFootprints = psMetadataLookupBool(NULL, recipe, "USE_FOOTPRINTS");

    // on first pass, detections have not yet been allocated
    if (!detections) {
	detections = pmDetectionsAlloc();
	pass = 1;
        NSIGMA_PEAK = psMetadataLookupF32 (&status, recipe, "PEAKS_NSIGMA_LIMIT"); PS_ASSERT (status, NULL);
        NMAX = psMetadataLookupS32 (&status, recipe, "PEAKS_NMAX"); PS_ASSERT (status, NULL);
    } else {
	pass = 2;
        NSIGMA_PEAK = psMetadataLookupF32 (&status, recipe, "PEAKS_NSIGMA_LIMIT_2"); PS_ASSERT (status, NULL);
	NMAX = 0; // unlimited number of peaks in final pass: allow a limit (PEAKS_NMAX_2) ?
    }

    float threshold = PS_SQR(NSIGMA_PEAK);

    // move the old peaks array (if it exists) to oldPeaks 
    // XXX generically, we should be able to call this function an arbitrary number of times
    assert (detections->oldPeaks == NULL);
    detections->oldPeaks = detections->peaks;
    detections->peaks = NULL;

    // generate the smoothed significance image
    psImage *significance = psphotSignificanceImage (readout, recipe, pass, maskVal);

    // detect the peaks in the significance image
    detections->peaks = psphotFindPeaks (significance, readout, recipe, threshold, NMAX);
    psMetadataAddF32  (recipe, PS_LIST_TAIL, "PEAK_THRESHOLD", PS_META_REPLACE, "Peak Detection Threshold", threshold);

    // optionally merge peaks into footprints
    if (useFootprints) {
	psphotFindFootprints (detections, significance, readout, recipe, pass, maskVal);
    }

    psFree (significance);
    return detections;
}

// if we use the footprints, the output peaks list contains both old and new peaks,
// otherwise it only contains the new peaks.
