/** @file ippToPspsBatchDifference.c
 *
 *  @ingroup ippToPsps
 *
 *  @author IfA
 *  Copyright 2009 Institute for Astronomy, University of Hawaii
 */

#include "ippToPsps.h"
#include "ippToPspsConfig.h"
#include "ippToPspsDiffEnums.h"

/**
  \brief Loops round all the diff cmf files (one per skycell) and generates one FITS  
  */
int ippToPsps_batchDifference(IppToPsps *this) {

    if (this->numOfInputFiles < 1) return PS_EXIT_DATA_ERROR;

    uint32_t skycell = 0; // TODO
    long tableSize;
    float SIG_CONST = 5.0; // TODO
    double obsTime;
    float obsTimes[MAXDETECT];

    char skycellStr[10];
    char extensionName[20];
    sprintf(extensionName, "SkyChip.psf");

    int status;
    fitsfile *fitsIn;         
    int nKeys;
    status=0;

    float psfSigma[MAXDETECT];
    long numLowSig = 0;
    long numHighSig = 0;
    long highSig[MAXDETECT];
    long lowSig[MAXDETECT];
    int anynull = 0;
    float floatnull = -999.0;

    for (uint16_t i = 0; i<this->numOfInputFiles; i++) {

        if (fits_open_file(&fitsIn, this->inputFiles[i], READONLY, &status)) {

            psError(PS_ERR_IO, false, "Unable to open file: '%s'", this->inputFiles[i]);
            break; 
        }

        //psLogMsg("ippToPsps", PS_LOG_INFO,"Opened %s", this->inputFiles[i]);

        skycell = i; // TODO
        sprintf(skycellStr, "SC%03d", skycell);

        // build StackMeta from primary header
        fits_get_hdrspace(fitsIn, &nKeys, NULL, &status);
        ippToPspsConfig_writeTable(this->config, fitsIn,  this->fitsOut, 1, "StackMeta", true);
        fits_write_col(this->fitsOut, TLONG, STACKMETA_SKYCELLID, 1, 1, 1, &skycell, &status);

        // build StackToImage
        ippToPspsConfig_writeTable(this->config, fitsIn,  this->fitsOut, 1, "StackToImage", true);
        //  psMetadataAdd(headerOut, PS_LIST_TAIL, "SKYCELL_ID", PS_DATA_S32, "Skycell ID", skycell);

        // save some stuff for later
        status=0; fits_read_key(fitsIn, TDOUBLE, "MJD-OBS", &obsTime, NULL, &status);

        if (fits_movnam_hdu(fitsIn, BINARY_TBL, extensionName, 0, &status)) {
            psError(PS_ERR_IO, false, "Can't move to extension: %s skipping\n", extensionName);
            continue;
        }
        if (fits_get_num_rows(fitsIn, &tableSize, &status)) {
            psError(PS_ERR_IO, false, "Can't count rows in extension: %s skipping\n", extensionName);
            continue;
        }

        numLowSig = numHighSig = 0;

        //  get magnitude error (PSF_INST_MAG_SIG)
        fits_read_col(fitsIn, TFLOAT, 9, 1, 1, tableSize, &floatnull, psfSigma, &anynull, &status);

        for (long j = 0; j<tableSize; j++) {

            obsTimes[j] = obsTime;

            // split between low and high 'significance difference detections'
            if (psfSigma[j] > (1.0/SIG_CONST)) {

                //     psMetadataAdd(rowOut, 0, "stackMetaID", PS_DATA_S64, "reference to stack", 0); // TODO
                lowSig[numLowSig] = j+1;
                numLowSig++;
            }
            else {

                highSig[numHighSig] = j+1;
                numHighSig++;
            }
        }

        psLogMsg("ippToPsps", PS_LOG_INFO, 
                "Reading skycell '%d'. High significant detections = %ld low significant detections = %ld", 
                skycell, numHighSig, numLowSig);

        //  psMetadataAdd(headerOut, PS_LIST_TAIL, "SKYCELL_ID", PS_DATA_S32, "Skycell ID", skycell);

        // write out low and high significant tables
        ippToPspsConfig_writeTable(this->config, fitsIn, this->fitsOut, 1, "StackLowSigDelta", false);
        ippToPspsConfig_writeTable(this->config, fitsIn, this->fitsOut, tableSize, "StackHighSigDelta", false);
        fits_write_col(this->fitsOut, TFLOAT, STACKHIGHSIGDELTA_OBSTIME, 1, 1, tableSize, obsTimes, &status);
        if (numLowSig) fits_delete_rowlist(this->fitsOut, lowSig, numLowSig, &status);


        //   psMetadataAdd(headerOut, PS_LIST_TAIL, "SKYCELL_ID", PS_DATA_S32, "Skycell ID", skycell);

        if (fits_close_file(fitsIn, &status)) fits_report_error(stderr, status);
    }

    return PS_EXIT_SUCCESS;
}
