# include "pswarp.h"

// This function is called by the stand-alone pswarp program to set the mask values in the
// config file.  It sets the named mask values MASK.PSPHOT and MARK.PSPHOT in the PSPHOT
// recipe.  Functions or programs which call psphotReadout as a library function must set these
// named mask values in the PSPHOT recipe on their own.  This function should only be called
// after the first header of the input mask image has been loaded and the named mask bits
// updated in the config metadata.

bool pswarpSetMaskBits (pmConfig *config) {

    psMaskType maskIn = 0x00;			// mask for the input image
    psMaskType markIn = 0x00;			// mark for the input image
    psMaskType maskOut = 0x00;			// mask for the output image
    psMaskType markOut = 0x00;			// mark for the output image

    // this function sets the required single-image mask bits
    if (!pmConfigMaskSetBits (&maskIn, &markIn, config)) {
	psError (PS_ERR_UNKNOWN, true, "Unable to define the mask bit values");
	return false;
    }

    // mask for non-linear flat regions (default to DETECTOR if not defined)
    psMaskType badMask = pmConfigMaskGet("BAD.WARP", config); 
    if (!badMask) {
	badMask = 0x01;
	pmConfigMaskSet (config, "BAD.WARP", badMask);
    }
    maskOut |= badMask;

    // mask for non-linear flat regions (default to DETECTOR if not defined)
    psMaskType poorMask = pmConfigMaskGet("POOR.WARP", config); 
    if (!poorMask) {
	poorMask = 0x02;
	pmConfigMaskSet (config, "POOR.WARP", poorMask);
    }
    maskOut |= poorMask;

    // search for an unset bit to use for MARK:
    markOut = 0x80;

    int nBits = sizeof(psMaskType) * 8;
    for (int i = 0; !markOut && (i < nBits); i++) {
	if (maskOut & markOut) {
	    markOut >>= 1;
	} else {
	    markOut = markOut;
	}
    }

    if (!markOut) {
	psError (PS_ERR_UNKNOWN, true, "Unable to define the MARK bit mask: all bits taken!");
	return false;
    }

    // update the pswarp recipe
    psMetadata *warpRecipe = psMetadataLookupPtr (NULL, config->recipes, PSWARP_RECIPE);
    if (!warpRecipe) {
        psError(PSPHOT_ERR_CONFIG, false, "missing recipe %s", PSWARP_RECIPE);
        return false;
    }

    // set maskOut and markOut in the psphot recipe
    // NOTE: psphot works on the output images, not input images, so set the MARK and MASK correctly here
    psMetadataAddU8 (warpRecipe, PS_LIST_TAIL, "MASK.INPUT",  PS_META_REPLACE, "user-defined mask", maskIn);
    psMetadataAddU8 (warpRecipe, PS_LIST_TAIL, "MARK.INPUT",  PS_META_REPLACE, "user-defined mask", markIn);
    psMetadataAddU8 (warpRecipe, PS_LIST_TAIL, "MASK.OUTPUT", PS_META_REPLACE, "user-defined mask", maskOut);
    psMetadataAddU8 (warpRecipe, PS_LIST_TAIL, "MARK.OUTPUT", PS_META_REPLACE, "user-defined mask", markOut);

    // update the psphot recipe
    psMetadata *psphotRecipe = psMetadataLookupPtr (NULL, config->recipes, PSPHOT_RECIPE);
    if (!psphotRecipe) {
        psError(PSPHOT_ERR_CONFIG, false, "missing recipe %s", PSPHOT_RECIPE);
        return false;
    }

    // set maskOut and markOut in the psphot recipe
    // NOTE: psphot works on the output images, not input images, so set the MARK and MASK correctly here
    psMetadataAddU8 (psphotRecipe, PS_LIST_TAIL, "MARK.PSPHOT", PS_META_REPLACE, "user-defined mask", markOut);
    psMetadataAddU8 (psphotRecipe, PS_LIST_TAIL, "MASK.PSPHOT", PS_META_REPLACE, "user-defined mask", maskOut);

    return true;
}
