#include <stdio.h>
#include "pslib.h"
#include "papmodule.h"
#include "papFocalPlane.h"

psMemoryId memPrint(const psMemBlock *ptr)
{
    fprintf(stderr, "File: %s\n", ptr->file);
    fprintf(stderr, "Memory block %qd:\n"
	    "\tFile %s, line %d, size %d\n"
	    "\tRefCounter: %qd\n"
	    "\tPosts: %x %x %x\n",
	    ptr->id, ptr->file, ptr->lineno, ptr->userMemorySize, ptr->refCounter,
	    ptr->startblock, ptr->endblock, *(psPtr *)((int8_t *) (ptr + 1) + ptr->userMemorySize));
    return 0;
}
 
int main(int argc, char *argv[])
{
#if 0
    psMemAllocateCallbackSet(memPrint);
    psMemAllocateCallbackSetID(921);
    psMemFreeCallbackSet(memPrint);
    psMemFreeCallbackSetID(921);
#endif

    (void)psTraceSetLevel(".", 0);
    (void)psTraceSetLevel("readExtension", 10);
    (void)psTraceSetLevel("readMultipleRegions", 0);
    (void)psTraceSetLevel("portions", 0);
    (void)psTraceSetLevel("pmFPAPrint", 10);
    (void)psTraceSetLevel("pmFPAfromHeader", 10);
    (void)psTraceSetLevel("pmCameraFromHeader", 10);
    (void)psTraceSetLevel("pmFPAMorph", 10);
    (void)psTraceSetLevel("spliceCells", 10);


    if (argc != 3) {
	printf("Usage: %s IPP_CONFIG IMAGE\n", argv[0]);
	exit(EXIT_FAILURE);
    }
    const char *ipprcName = argv[1];
    const char *imageName = argv[2];

    int badLines = 0;			// Number of bad lines in camera configuration
    psMetadata *ipprc = psMetadataConfigParse(NULL, &badLines, ipprcName, true); // Read IPP config file
    if (badLines > 0) {
	psLogMsg(__func__, PS_LOG_WARN, "%d bad lines encountered while reading IPP configuration %s\n",
		 badLines, ipprcName);
    }

    psFits *fits = psFitsAlloc(imageName);
    psMetadata *header = psFitsReadHeader(NULL, fits);

    psMetadata *camera = pmCameraFromHeader(header, ipprc);

    papFPA *fpa = pmFPAConstruct(camera, NULL);

    // Cut off a lot of the chips so I can fit things in memory
    {
	psArray *chips = fpa->chips;
	papChip *chip = chips->data[0];
	psFree(chips);
	chips = psArrayAlloc(1);
	chips->data[0] = chip;
    }

    (void)pmFPARead(fpa, fits);
    (void)pmFPAPrint(fpa);

    // Morph to a splice image
    psMetadata *newCamera = psMetadataConfigParse(NULL, &badLines, "megacam_splice.config", true);
    papFPA *newfpa = pmFPAConstruct(newCamera, NULL);

    // Cut off a lot of the chips so I can fit things in memory
    {
	psArray *chips = newfpa->chips;
	papChip *chip = chips->data[0];
	psFree(chips);
	chips = psArrayAlloc(1);
	chips->data[0] = chip;
    }

    pmFPAPrint(newfpa);
    pmFPAMorph(newfpa, fpa, 0, 0);
    pmFPAPrint(newfpa);

#if 0
    // Write out
    psFits *newfits = psFitsAlloc("test.fits");
    pmFPAWrite(fits, newfpa);
    psFree(newfits);
#endif

#if 1
    psArray *chips = newfpa->chips;
    for (int i = 0; i < chips->n; i++) {
	papChip *chip = chips->data[i];	// Chip of interest
	psArray *cells = chip->cells;	// Array of cells

	if (chip->extname) {
	    psFits *fp = psFitsAlloc(chip->extname);
	    psFitsWriteImage(fp, chip->header, chip->pixels->data[i], i);
	    psFree(fp);
	}

	for (int j = 0; j < cells->n; j++) {
	    papCell *cell = cells->data[j]; // Cell of interest

	    if (cell->extname) {
		psFits *fp = psFitsAlloc(cell->extname);
		psFitsWriteImage(fp, cell->header, cell->pixels->data[i], i);
		psFree(fp);
	    }
	}
    }
#endif

    psFree(newfpa);
    psFree(newCamera);

    // Tidy up
    psMemCheckCorruption(true);

    psFree(camera);
    psFree(fits);

    psFree(fpa);

    return 0;
}
