# include "pswarp.h"
// this function loads the skycell metadata

bool pswarpDefine (pmConfig *config) {

    // load the PSWARP recipe
    psMetadata *recipe = psMetadataLookupPtr (NULL, config->recipes, PSWARP_RECIPE);
    if (!recipe) {
        psError(PSWARP_ERR_CONFIG, true, "Can't find PSWARP recipe!\n");
        return false;
    }

    // select the input data sources
    pmFPAfile *skycell = psMetadataLookupPtr (NULL, config->files, "PSWARP.SKYCELL");
    if (!skycell) {
        psError(PSWARP_ERR_CONFIG, false, "Can't find skycell data!\n");
        return false;
    }
    pmFPAfile *output = psMetadataLookupPtr(NULL, config->files, "PSWARP.OUTPUT");
    if (!output) {
        psError(PSWARP_ERR_CONFIG, false, "Can't find output data!\n");
        return false;
    }
    pmFPAfile *input = psMetadataLookupPtr(NULL, config->files, "PSWARP.INPUT");
    if (!input) {
        psError(PSWARP_ERR_CONFIG, false, "Can't find input data!\n");
        return false;
    }

    // open the full skycell file; no need to defer different depths. only load the header data
    pmFPAview *view = pmFPAviewAlloc (0);
    pmFPAfileOpen (skycell, view, config);

    // Read header and create target
    {
        if (!pmFPAReadHeaderSet(skycell->fpa, skycell->fits, config->database)) {
            psError(PS_ERR_UNKNOWN, false, "Unable to read headers for skycell.");
            psFree(view);
            return false;
        }
        view->chip = 0;
        view->cell = 0;
        view->readout = 0;
        pmCell *source = pmFPAfileThisCell(config->files, view, "PSWARP.SKYCELL"); // Source cell
        pmHDU *hdu = pmHDUFromCell(source); // HDU for source
        if (!hdu || !hdu->header) {
            psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to find header for sky cell.");
            psFree(view);
            return false;
        }
        int numCols = psMetadataLookupS32(NULL, hdu->header, "NAXIS1"); // Number of columns
        int numRows = psMetadataLookupS32(NULL, hdu->header, "NAXIS2"); // Number of rows

        pmCell *target = pmFPAviewThisCell(view, output->fpa); // Target cell
        pmReadout *readout = pmReadoutAlloc(target); // Target readout
        readout->image = psImageAlloc(numCols, numRows, PS_TYPE_F32);
        psImageInit(readout->image, NAN);
        psFree(readout);                // Drop reference

        psMetadataItemSupplement(target->concepts, source->concepts, "CELL.XBIN");
        psMetadataItemSupplement(target->concepts, source->concepts, "CELL.YBIN");
        psMetadataItemSupplement(target->concepts, source->concepts, "CELL.XSIZE");
        psMetadataItemSupplement(target->concepts, source->concepts, "CELL.YSIZE");
        psMetadataItemSupplement(target->concepts, source->concepts, "CELL.XPARITY");
        psMetadataItemSupplement(target->concepts, source->concepts, "CELL.YPARITY");
        psMetadataItemSupplement(target->concepts, source->concepts, "CELL.X0");
        psMetadataItemSupplement(target->concepts, source->concepts, "CELL.Y0");
    }

    // XXX this is not a sufficient test
    view->chip = 0;
    view->cell = 0;
    view->readout = -1;
    pmHDU *phu = pmFPAviewThisPHU(view, skycell->fpa); // Skycell PHU
    pmHDU *hdu = pmFPAviewThisHDU(view, skycell->fpa); // Skycell header
    bool bilevelAstrometry = false;
    if (phu) {
        char *ctype = psMetadataLookupStr(NULL, phu->header, "CTYPE1");
        if (ctype) {
            bilevelAstrometry = !strcmp(&ctype[4], "-DIS");
        }
    }

    // We read from the skycell into the output.  i.e., the output receives the desired astrometry.
    pmChip *outputChip = pmFPAviewThisChip(view, output->fpa); // Chip in the output
    if (bilevelAstrometry) {
        if (!pmAstromReadBilevelMosaic(output->fpa, phu->header)) {
            psError(PS_ERR_UNKNOWN, false, "Unable to read bilevel mosaic astrometry for skycell.");
            psFree(view);
            return false;
        }
        if (!pmAstromReadBilevelChip(outputChip, hdu->header)) {
            psError(PS_ERR_UNKNOWN, false, "Unable to read bilevel chip astrometry for skycell.");
            psFree(view);
            return false;
        }
    } else {
        // we use a default FPA pixel scale of 1.0
        if (!pmAstromReadWCS(output->fpa, outputChip, hdu->header, 1.0)) {
            psError(PS_ERR_UNKNOWN, false, "Unable to read WCS astrometry for skycell.");
            psFree(view);
            return false;
        }
    }

    const char *name = psMetadataLookupStr(NULL, input->fpa->concepts, "FPA.NAME"); // Name of FPA
    view->chip = view->cell = view->readout = -1;
    pmFPAAddSourceFromView(output->fpa, name, view, output->format);

    psFree (view);
    return true;
}
