# include "psphotInternal.h"

// XXX let's make a better distinction between 'pass' (used for counting intput / output
// entries) and needing/having a PSF.  In this function, we smooth the image, then search for
// the peaks
pmDetections *psphotFindDetections (pmDetections *detections, pmReadout *readout, psMetadata *recipe) {

    bool status;
    int pass;

    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;
    } else {
	pass = 2;
    }

    // move the old peaks array (if it exists) to oldPeaks 
    assert (detections->oldPeaks == NULL);
    detections->oldPeaks = detections->peaks;
    detections->peaks = NULL;

    // if footprints are not requested, find the peaks and return them
    if (!useFootprints) {
	detections->peaks = psphotFindPeaks (readout, recipe, useFootprints, pass, maskVal);
	return detections;
    }

    // psphotFindPeaks returns a different set of objects if useFootprints is true!
    // XXX fix this by splitting psphotFindPeaks into smooth / peaks / footprint stages?
    psArray *footprints = psphotFindPeaks (readout, recipe, useFootprints, pass, maskVal);

    int growRadius = 0;
    if (pass == 1) {
	growRadius = psMetadataLookupS32(NULL, recipe, "FOOTPRINT_GROW_RADIUS");
    } else {
	growRadius = psMetadataLookupS32(NULL, recipe, "FOOTPRINT_GROW_RADIUS_2");
    }

    if (growRadius > 0) {
	psArray *tmp = pmGrowFootprintArray(footprints, growRadius);
	psFree(footprints);
	footprints = tmp;
    }

    if (pass == 2) {
	// merge in old peaks;
	const int includePeaks = 0x0 | 0x2; // i.e. just from newFootprints
	
	psLogMsg ("psphot", PS_LOG_INFO, "merging %ld new footprints into %ld existing ones\n", footprints->n, detections->footprints->n);
	psArray *mergedFootprints = pmMergeFootprintArrays(detections->footprints, footprints, includePeaks);
	psFree(footprints);
	psFree(detections->footprints);
	detections->footprints = mergedFootprints;
    } else {
	detections->footprints = footprints;
    }

    psphotCullPeaks(readout->image, readout->weight, recipe, detections->footprints);
    detections->peaks = pmFootprintArrayToPeaks(detections->footprints);
    psLogMsg ("psphot", PS_LOG_INFO, "%ld peaks, %ld total footprints: %f sec\n", detections->peaks->n, detections->footprints->n, psTimerMark ("psphot"));

    return detections;
}

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

// if psf is defined, we should treat this as pass "2", not "1".  re-define this boolean to
// be "have PSF"
