# include "psphotStandAlone.h"

# define ESCAPE(MESSAGE) { \
  psError(PSPHOT_ERR_DATA, false, MESSAGE); \
  psFree (view); \
  return false; \
}

bool psphotImageLoop (pmConfig *config) {

    bool status;
    pmChip *chip;
    pmCell *cell;
    pmReadout *readout;

    pmFPAfile *load = psMetadataLookupPtr (&status, config->files, "PSPHOT.LOAD");
    if (!status) {
	psError(PSPHOT_ERR_PROG, false, "Can't find input data!");
	return false;
    }
    pmFPAfile *input = psMetadataLookupPtr (&status, config->files, "PSPHOT.INPUT");
    if (!status) {
	psError(PSPHOT_ERR_PROG, false, "Can't find input data!");
	return false;
    }

    pmFPAview *view = pmFPAviewAlloc (0);
    
    // files associated with the science image
    if (!pmFPAfileIOChecks (config, view, PM_FPA_BEFORE)) ESCAPE ("failed input for fpa in psphot.");

    // for psphot, we force data to be read at the chip level 
    while ((chip = pmFPAviewNextChip (view, load->fpa, 1)) != NULL) {
        psLogMsg ("psphot", 4, "Chip %d: %x %x\n", view->chip, chip->file_exists, chip->process);
        if (! chip->process || ! chip->file_exists) { continue; }

	// load just the input image data (image, mask, weight)
	pmFPAfileActivate (config->files, false, NULL);
	pmFPAfileActivate (config->files, true, "PSPHOT.LOAD");
	pmFPAfileActivate (config->files, true, "PSPHOT.MASK");
	pmFPAfileActivate (config->files, true, "PSPHOT.WEIGHT");
	if (!pmFPAfileIOChecks (config, view, PM_FPA_BEFORE)) ESCAPE ("failed input for Chip in psphot.");

	// mosaic the cells of a chip into a single contiguous (trimmed) chip
        if (!psphotMosaicChip(config, view, "PSPHOT.INPUT", "PSPHOT.LOAD")) ESCAPE ("Unable to mosaic chip.");

	// try to load other supporting data (PSF, SRC, etc).
	// do not re-load the following three files
	pmFPAfileActivate (config->files, true, NULL);
	pmFPAfileActivate (config->files, false, "PSPHOT.LOAD");
	pmFPAfileActivate (config->files, false, "PSPHOT.MASK");
	pmFPAfileActivate (config->files, false, "PSPHOT.WEIGHT");
	if (!pmFPAfileIOChecks (config, view, PM_FPA_BEFORE)) ESCAPE ("failed input for Chip in psphot.");

	// re-activate files so they will be closed and freed below
	pmFPAfileActivate (config->files, true, NULL);

	// there is now only a single chip (multiple readouts?). loop over it and process
	while ((cell = pmFPAviewNextCell (view, input->fpa, 1)) != NULL) {
            psLogMsg ("psphot", 5, "Cell %d: %x %x\n", view->cell, cell->file_exists, cell->process);

	    // process each of the readouts
	    while ((readout = pmFPAviewNextReadout (view, input->fpa, 1)) != NULL) {
		psLogMsg ("psphot", 6, "Cell %d: %x %x\n", view->cell, cell->file_exists, cell->process);
		if (! readout->data_exists) { continue; }

		// run the actual photometry analysis on this chip/cell/readout
		if (!psphotReadout (config, view)) {
		    psError(psErrorCodeLast(), false, "failure in psphotReadout for chip %d, cell %d, readout %d\n", view->chip, view->cell, view->readout);
		    psFree (view);
		    return false;
		}
	    }

	    status = true;
	    status &= pmFPAfileDropInternal (config->files, "PSPHOT.BACKMDL");
	    status &= pmFPAfileDropInternal (config->files, "PSPHOT.BACKMDL.STDEV");
	    status &= pmFPAfileDropInternal (config->files, "PSPHOT.BACKGND");
	    if (!status) {
		psError(PSPHOT_ERR_PROG, false, "trouble dropping internal files");
		psFree (view);
		return false;
	    }
	}

	// save output which is saved at the chip level
	if (!pmFPAfileIOChecks (config, view, PM_FPA_AFTER)) ESCAPE ("failed output for Chip in psphot.");
    }
    // save output which is saved at the fpa level
    if (!pmFPAfileIOChecks (config, view, PM_FPA_AFTER)) ESCAPE ("failed ouput for FPA in psphot.");

    // fail if we failed to handle an error
    if (psErrorCodeLast() != PS_ERR_NONE) psAbort ("failed to handle an error!");

    psFree (view);
    return true;
}

// I/O files related to psphot:
// PSPHOT.INPUT   : input image file(s)
// PSPHOT.RESID   : residual image
// PSPHOT.OUTPUT  : output object tables (object)

// PSPHOT.BACKSUB : background subtracted image
// PSPHOT.BACKGND : background model (full-scale image?)
// PSPHOT.BACKMDL : background model (binned image?)
// PSPHOT.PSF     : sample PSF images

// PSPHOT.MASK
// PSPHOT.WEIGHT
// 
