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

#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <pslib.h>

#include "pmHDU.h"
#include "pmFPA.h"
#include "pmConceptsUpdate.h"

bool pmConceptsUpdate(const pmFPA *fpa, const pmChip *chip, const pmCell *cell)
{
    if (fpa) {
        // Check for FPA concepts updates
    }

    if (chip) {
        // Check for chip concepts updates
    }

    if (cell) {
        // Check for cell concepts updates

	bool xStatus, yStatus; // Status of MD lookups
	psImageBinning *binning = psImageBinningAlloc();
	binning->nXbin = psMetadataLookupS32(&xStatus, cell->concepts, "CELL.XBIN");
	binning->nYbin = psMetadataLookupS32(&yStatus, cell->concepts, "CELL.YBIN");
	if (!xStatus || !yStatus) {
	    // XXX should this be an error condition?
	    psFree (binning);
	    return true;
	}
	if (!binning->nXbin || !binning->nXbin) {
	    // XXX should this be an error condition?
	    psFree (binning);
	    return true;
	}

        // CELL.TRIMSEC needs to be updated for the binning
        if (psMetadataLookup(cell->concepts, "CELL.TRIMSEC.UPDATE")) {
	    psRegion *trimsec = psMetadataLookupPtr(NULL, cell->concepts, "CELL.TRIMSEC"); // Trim section
	    *trimsec = psImageBinningSetRuffRegion (binning, *trimsec);
	    // force integer pixels : truncate x0, roundup x1:
	    trimsec->x0 = (int)trimsec->x0;
	    if (trimsec->x1 > (int)trimsec->x1) {
		trimsec->x1 = (int)trimsec->x1 + 1;
	    } else {
		trimsec->x1 = (int)trimsec->x1;
	    }		
	    trimsec->y0 = (int)trimsec->y0;
	    if (trimsec->y1 > (int)trimsec->y1) {
		trimsec->y1 = (int)trimsec->y1 + 1;
	    } else {
		trimsec->y1 = (int)trimsec->y1;
	    }		
	    psMetadataRemoveKey(cell->concepts, "CELL.TRIMSEC.UPDATE");
        }

        // CELL.BIASSEC needs to be updated for the binning
        if (psMetadataLookup(cell->concepts, "CELL.BIASSEC.UPDATE")) {
	    psList *biassecs = psMetadataLookupPtr(NULL, cell->concepts, "CELL.BIASSEC"); // Bias sections
	    psListIterator *biassecsIter = psListIteratorAlloc(biassecs, PS_LIST_HEAD, true); // Iterator
	    psRegion *biassec; // Bias region, from iteration
	    while ((biassec = psListGetAndIncrement(biassecsIter))) {
		*biassec = psImageBinningSetRuffRegion (binning, *biassec);
		// force integer pixels : truncate x0, roundup x1:
		biassec->x0 = (int)biassec->x0;
		if (biassec->x1 > (int)biassec->x1) {
		    biassec->x1 = (int)biassec->x1 + 1;
		} else {
		    biassec->x1 = (int)biassec->x1;
		}		
		biassec->y0 = (int)biassec->y0;
		if (biassec->y1 > (int)biassec->y1) {
		    biassec->y1 = (int)biassec->y1 + 1;
		} else {
		    biassec->y1 = (int)biassec->y1;
		}		
	    }
	    psFree(biassecsIter);
	    psMetadataRemoveKey(cell->concepts, "CELL.BIASSEC.UPDATE");
        }
	psFree (binning);
    }

    return true;
}
