# include "psastroInternal.h"

bool psastroDefineFiles (pmConfig *config, pmFPAfile *input) {

    // these calls bind the I/O handle to the specified fpa
    bool status;

    // select the current recipe
    psMetadata *recipe  = psMetadataLookupPtr (&status, config->recipes, PSASTRO_RECIPE);
    if (!recipe) {
	psError(PSASTRO_ERR_CONFIG, false, "Can't find PSASTRO recipe!\n");
	return false;
    }

    pmFPAfile *output = pmFPAfileDefineOutput (config, input->fpa, "PSASTRO.OUTPUT");
    if (!output) {
	psError(PSASTRO_ERR_CONFIG, false, "Failed to build FPA from PSASTRO.INPUT");
	return false;
    }
    output->save = true;

    bool fixChips = psMetadataLookupBool (&status, config->arguments, "PSASTRO.FIX.CHIPS");
    if (!status) {
	fixChips = psMetadataLookupBool (&status, recipe, "PSASTRO.FIX.CHIPS");
    }
    bool useModel = psMetadataLookupBool (&status, config->arguments, "PSASTRO.USE.MODEL");
    if (!status) {
	fixChips = psMetadataLookupBool (&status, recipe, "PSASTRO.USE.MODEL");
    }
    if (fixChips || useModel) {
        if (!psastroDefineFile (config, input->fpa, "PSASTRO.MODEL", "ASTROM.MODEL", PM_FPA_FILE_ASTROM_MODEL, PM_DETREND_TYPE_ASTROM)) {
            psError (PS_ERR_IO, false, "Can't find an astrometry model file");
            return NULL;
        }
    }

    // this step is optional
    bool REFSTAR_MASK = psMetadataLookupBool (&status, recipe, "REFSTAR_MASK");
    if (REFSTAR_MASK) {

        if (!psastroDefineFile (config, input->fpa, "PSASTRO.REFMASK", "REFMASK", PM_FPA_FILE_MASK, PM_DETREND_TYPE_MASK)) {
            psError (PS_ERR_IO, false, "Can't find an input mask file");
            return NULL;
        }

        if (!psastroDefineFile (config, input->fpa, "PSASTRO.INPUT.MASK", "INPUT.MASK", PM_FPA_FILE_MASK, PM_DETREND_TYPE_MASK)) {
            psError (PS_ERR_IO, false, "Can't find an input mask file");
            return NULL;
        }

	pmFPAfile *inMask = psMetadataLookupPtr (NULL, config->files, "PSASTRO.INPUT.MASK");
	if (!inMask) {
            psError (PS_ERR_IO, false, "Can't find an input mask file");
            return NULL;
        }

	// XXX not yet sure if we need to mosaic or not...
	pmFPAfile *outMask = pmFPAfileDefineOutputFromFile  (config, inMask, "PSASTRO.OUTPUT.MASK");
	// pmFPAfile *outMask = pmFPAfileDefineChipMosaic(config, inMask->fpa, "PSASTRO.OUTPUT.MASK");
	if (!outMask) {
	    psError (PS_ERR_IO, false, "Can't find the astrometry refstars file definition");
	    return NULL;
	}
	if (outMask->type != PM_FPA_FILE_MASK) {
	    psError(PS_ERR_IO, true, "%s is not of type %s", "PSASTRO.OUTPUT.MASK", pmFPAfileStringFromType (PM_FPA_FILE_MASK));
	    return NULL;
	}
	outMask->save = true;
	inMask->freeLevel = outMask->dataLevel;
    }

    bool saveRefstars = psMetadataLookupBool (&status, config->arguments, "PSASTRO.SAVE.REFSTARS");
    if (!status) {
      saveRefstars = psMetadataLookupBool (&status, recipe, "PSASTRO.SAVE.REFSTARS");
    }
    if (saveRefstars) {
	// look for the file in the camera config table
	pmFPAfile *file = pmFPAfileDefineOutputFromFile  (config, input, "PSASTRO.OUT.REFSTARS");
	if (!file) {
	    psError (PS_ERR_IO, false, "Can't find the astrometry refstars file definition");
	    return NULL;
	}
	if (file->type != PM_FPA_FILE_ASTROM_REFSTARS) {
	    psError(PS_ERR_IO, true, "%s is not of type %s", "PSASTRO.OUT.REFSTARS", pmFPAfileStringFromType (PM_FPA_FILE_ASTROM_REFSTARS));
	    return NULL;
	}
	file->save = true;
    }


# if (0)
    // optionally save output plots
    if (!pmFPAfileDefineOutput (config, input->fpa, "SOURCE.PLOT.MOMENTS")) {
	psTrace ("psphot", 3, "Cannot find a rule for SOURCE.PLOT.MOMENTS");
    }
    if (!pmFPAfileDefineOutput (config, input->fpa, "SOURCE.PLOT.PSFMODEL")) {
	psTrace ("psphot", 3, "Cannot find a rule for SOURCE.PLOT.PSFMODEL");
    }
# endif

    return true;
}

bool psastroDefineFile (pmConfig *config, pmFPA *input, char *filerule, char *argname, pmFPAfileType fileType, pmDetrendType detrendType) {

    bool status;
    pmFPAfile *file;

    // look for the file on the argument list
    file = pmFPAfileDefineFromArgs  (&status, config, filerule, argname);
    if (!status) {
	psError (PS_ERR_UNKNOWN, false, "failed to load find definition");
	return false;
    }
    if (file) {
	if (file->type != fileType) {
	    psError(PS_ERR_IO, true, "%s is not of type %s", filerule, pmFPAfileStringFromType (fileType));
	    return false;
	}
	return true;
    }

    // look for the file in the camera config table
    file = pmFPAfileDefineFromConf  (&status, config, filerule);
    if (!status) {
	psError (PS_ERR_UNKNOWN, false, "failed to load find definition");
	return false;
    }
    if (file) {
	if (file->type != fileType) {
	    psError(PS_ERR_IO, true, "%s is not of type %s", filerule, pmFPAfileStringFromType (fileType));
	    return false;
	}
	return true;
    }

    // look for the file to be loaded from the detrend database
    file = pmFPAfileDefineFromDetDB (&status, config, filerule, input, detrendType);
    if (!status) {
	psError (PS_ERR_UNKNOWN, false, "failed to load file definition");
	return false;
    }
    if (file) {
	if (file->type != fileType) {
	    psError(PS_ERR_IO, true, "%s is not of type %s", filerule, pmFPAfileStringFromType (fileType));
	    return false;
	}
	return true;
    }
    return false;
}

