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

    // user-defined masks to test for good/bad pixels (build from recipe list if not yet set)
    psImageMaskType maskVal = psMetadataLookupImageMask(&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);

    // display the backsub and backgnd images
    psphotVisualShowSignificance (significance);

    // 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);
    if (!detections->peaks) {
        // No peaks found
        return NULL;
    }

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

    psFree (significance);

    // display the peaks and footprints
    psphotVisualShowPeaks (detections);
    psphotVisualShowFootprints (detections);

    return detections;
}

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