# include "psphotStandAlone.h"

static pmFPAfile *defineFile(pmConfig *config, pmFPAfile *bind, const char *name, const char *filename, pmFPAfileType type);

// define the needed / desired I/O files
bool psphotStackParseCamera (pmConfig *config) {

    bool status = false;

    // the input images are defined as a set of metadatas in the INPUTS metadata folder
    psMetadata *inputs = psMetadataLookupMetadata(&status, config->arguments, "INPUTS"); // The inputs info
    if (!inputs) {
	psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to find inputs.");
	return false;
    }

    int nInputs = inputs->list->n;
    for (int i = 0; i < nInputs; i++) {
	psMetadataItem *item = psMetadataGet(inputs, i);
	if (item->type != PS_DATA_METADATA) {
	    psError(PS_ERR_BAD_PARAMETER_TYPE, true, "Component %s of the input metadata is not of type METADATA", item->name);
	    return false;
	}

	psMetadata *input = item->data.md; // The input metadata of interest

	// look for 'IMAGE', 'MASK', 'VARIANCE' in folder (only 'IMAGE' is required)

	psString image = psMetadataLookupStr(NULL, input, "IMAGE"); // Name of image
	if (!image || strlen(image) == 0) {
	    psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Component %s lacks IMAGE of type STR", item->name);
	    return false;
	}
	pmFPAfile *imageFile = defineFile(config, NULL, "PSPHOT.INPUT", image, PM_FPA_FILE_IMAGE); // File for image
	if (!imageFile) {
	    psError(PS_ERR_UNKNOWN, false, "Unable to define file from image %d (%s)", i, image);
	    return false;
	}

	psString mask = psMetadataLookupStr(&status, input, "MASK"); // Name of mask
	if (mask && strlen(mask) > 0) {
	    if (!defineFile(config, imageFile, "PSPHOT.MASK", mask, PM_FPA_FILE_MASK)) {
		psError(PS_ERR_UNKNOWN, false, "Unable to define file from mask %d (%s)", i, mask);
		return false;
	    }
	}

	psString variance = psMetadataLookupStr(&status, input, "VARIANCE"); // Name of variance map
	if (variance && strlen(variance) > 0) {
	    if (!defineFile(config, imageFile, "PSPHOT.VARIANCE", variance, PM_FPA_FILE_VARIANCE)) {
		psError(PS_ERR_UNKNOWN, false, "Unable to define file from variance %d (%s)", i, variance);
		return false;
	    }
	}
	// the output sources are carried on the input->fpa structures
	pmFPAfile *outsources = pmFPAfileDefineOutputFromFile (config, imageFile, "PSPHOT.STACK.OUTPUT");
	if (!outsources) {
	    psError(PSPHOT_ERR_CONFIG, false, "Cannot find a rule for PSPHOT.STACK.OUTPUT");
	    return false;
	}
	outsources->save = true;
	outsources->fileID = i;		// this is used to generate output names
    }
    psMetadataRemoveKey(config->arguments, "FILENAMES");
    psMetadataAddS32 (config->arguments, PS_LIST_TAIL, "PSPHOT.INPUT.NUM", PS_META_REPLACE, "number of inputs", nInputs);

    if (!psphotSetMaskBits (config)) {
        psError (PS_ERR_UNKNOWN, false, "failed to set mask bit values");
        return NULL;
    }

    // generate an pmFPAimage for the chisqImage
    pmFPAfile *chisqImage = pmFPAfileDefineOutput(config, NULL, "PSPHOT.CHISQ.IMAGE");
    if (!chisqImage) {
        psError(PSPHOT_ERR_CONFIG, false, "Trouble defining PSPHOT.CHISQ.IMAGE");
        return false;
    }
    chisqImage->save = true;

    pmFPAfile *chisqMask = pmFPAfileDefineOutput(config, chisqImage->fpa, "PSPHOT.CHISQ.MASK");
    if (!chisqMask) {
        psError(PS_ERR_IO, false, _("Unable to generate output file from PSPHOT.CHISQ.MASK"));
        return NULL;
    }
    if (chisqMask->type != PM_FPA_FILE_MASK) {
        psError(PS_ERR_IO, true, "PSPHOT.CHISQ.MASK is not of type MASK");
        return NULL;
    }
    chisqMask->save = true;

    pmFPAfile *chisqVariance = pmFPAfileDefineOutput(config, chisqImage->fpa, "PSPHOT.CHISQ.VARIANCE");
    if (!chisqVariance) {
        psError(PS_ERR_IO, false, _("Unable to generate output file from PSPHOT.CHISQ.VARIANCE"));
        return NULL;
    }
    if (chisqVariance->type != PM_FPA_FILE_VARIANCE) {
        psError(PS_ERR_IO, true, "PSPHOT.CHISQ.VARIANCE is not of type VARIANCE");
        return NULL;
    }
    chisqVariance->save = true;

# if (0)    
    // define the additional input/output files associated with psphot
    // XXX figure out which files are needed by psphotStack
    if (false && !psphotDefineFiles (config, input)) {
        psError(PSPHOT_ERR_CONFIG, false, "Trouble defining the additional input/output files");
        return false;
    }
# endif

    psTrace("psphot", 1, "Done with psphotStackParseCamera...\n");

    psErrorClear();                     // some metadata lookup may have failed
    return true;
}

// Define a file
static pmFPAfile *defineFile(pmConfig *config, // Configuration
                             pmFPAfile *bind, // File to which to bind
                             const char *name, // Name of file rule
                             const char *filename, // Name of file
                             pmFPAfileType type // Type of file
                             )
{

    psArray *dummy = psArrayAlloc(1);   // Dummy array of filenames for this FPA
    dummy->data[0] = psStringCopy(filename);
    psMetadataAddArray(config->arguments, PS_LIST_TAIL, "FILENAMES", PS_META_REPLACE,
                       "Filenames for file rule definition", dummy);
    psFree(dummy);

    bool found = false;             // Found the file?
    pmFPAfile *file = bind ? pmFPAfileBindFromArgs(&found, bind, config, name, "FILENAMES") :
        pmFPAfileDefineFromArgs(&found, config, name, "FILENAMES");
    if (!file || !found) {
        psError(PS_ERR_UNKNOWN, false, "Unable to define file %s from %s", name, filename);
        return NULL;
    }
    if (file->type != type) {
        psError(PS_ERR_IO, true, "%s is not of type %s", name, pmFPAfileStringFromType(type));
        return NULL;
    }

    return file;
}

