#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include "dvoMakeCorr.h"

// XXX currently, the input image (the grid map generated by relphot) does not supply enough
// header information so the camera and format can be identified.

bool dvoMakeCorrLoop (pmConfig *config, dvoMakeCorrOptions *options) {

    bool status;
    pmChip *chip;
    pmCell *cell;
    psRegion fullImage = {0, 0, 0, 0};

    // psMetadata *recipe = psMetadataLookupMetadata(&status, config->recipes, RECIPE_NAME);

    // use the reference image to identify the desired extension from DVOCORR.INPUT
    pmFPAfile *refhead = psMetadataLookupPtr(&status, config->files, "DVOCORR.REFHEAD");
    if (!status) {
        psErrorStackPrint(stderr, "Can't find reference image\n");
        exit(EXIT_FAILURE);
    }

    pmFPAfile *input = psMetadataLookupPtr(&status, config->files, "DVOCORR.INPUT");
    if (!status) {
        psErrorStackPrint(stderr, "Can't find input data!\n");
        exit(EXIT_FAILURE);
    }

    pmFPAview *view = pmFPAviewAlloc(0);// View for level of interest

    // load data at FPA leve
    if (!pmFPAfileIOChecks(config, view, PM_FPA_BEFORE)) {
	psError(PS_ERR_UNKNOWN, false, "failed IO for fpa in psphot\n");
	psFree(view);
        return false;
    }

    // XXX for now, do not use the I/O system to read this file; do it manually
    if (!pmFPAfileOpen (input, view, config)) {
	psError(PS_ERR_UNKNOWN, false, "failed to open grid file\n");
	psFree (view);
	return false;
    }
    input->state = PM_FPA_STATE_INACTIVE;  

    // process each chip in the FPA
    while ((chip = pmFPAviewNextChip(view, refhead->fpa, 1)) != NULL) {
        psLogMsg ("dvoMakeCorrLoop", 4, "Chip %d: %x %x\n", view->chip, chip->file_exists, chip->process);
        if (!chip->process || !chip->file_exists) continue;
	if (!pmFPAfileIOChecks (config, view, PM_FPA_BEFORE)) {
            psError(PS_ERR_UNKNOWN, false, "failed IO for chip %d in dvoMakeCorr\n", view->chip);
	    psFree (view);
	    return false;
	}

	// load the input data for this extension
	pmChip *inChip = pmFPAviewThisChip (view, input->fpa);
	assert (inChip->hdu);
	assert (inChip->hdu->extname);
	psFitsMoveExtName (input->fits, inChip->hdu->extname);
	psImage *inImage = psFitsReadImage (input->fits, fullImage, 0);
	assert (inImage);

	// process each cell in the Chip
        while ((cell = pmFPAviewNextCell(view, refhead->fpa, 1)) != NULL) {
            psLogMsg ("dvoMakeCorrLoop", 4, "Cell %d: %x %x\n", view->cell, cell->file_exists, cell->process);
            if (!cell->process || !cell->file_exists) continue;
            if (!pmFPAfileIOChecks(config, view, PM_FPA_BEFORE)) {
		psError(PS_ERR_UNKNOWN, false, "failed IO for chip %d, cell %d in dvoMakeCorr\n", view->chip, view->cell);
		psFree (view);
		return false;
	    }

	    // XXX put the function here which unbins the input image
	    dvoMakeCorrUnbin (config, view, "DVOCORR.OUTPUT", inImage, inChip, "DVOCORR.REFHEAD");

	    if (!pmFPAfileIOChecks (config, view, PM_FPA_AFTER)) {
		psError(PS_ERR_UNKNOWN, false, "failed IO for chip %d, cell %d in dvoMakeCorr\n", view->chip, view->cell);
		psFree (view);
		return false;
	    }
	}
	psFree (inImage);

	if (!pmFPAfileIOChecks (config, view, PM_FPA_AFTER)) {
	    psError(PS_ERR_UNKNOWN, false, "failed IO for chip %d in dvoMakeCorr\n", view->chip);
	    psFree (view);
	    return false;
	}
    }
    if (!pmFPAfileIOChecks (config, view, PM_FPA_AFTER)) {
	psError(PS_ERR_UNKNOWN, false, "failed IO for fpa in dvoMakeCorr\n");
	psFree (view);
	return false;
    }

    pmFPAfileClose (input, view);
    psFree (view);

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

    return true;
}
