/** @file tst_pmFlatField.c
 *
 *  @brief Contains the tests for pmFlatField.c:
 *
 *    Test A - Divide input image by flat image
 *    Test B - Mask flat image data
 *    Test C - Mask flat image data starting with non-null mask
 *    Test E - Attempt to use null input image
 *    Test F - Attempt tp use null flat image
 *    Test G - Attempt to use input image bigger than flat image
 *    Test H - Attempt to use input image mask bigger than flat image
 *    Test I - Attempt to use offset greater than input image
 *    Test J - Attempt to use complex input image
 *    Test K - Attempt to use complex flat image
 *    Test L - Attempt to use non-equal input and flat image types
 *    Test M - Attempt to use non-mask type mask image
 *
 * XXX: Added a mask argument to pmFlatField().  Must add tests.  For now, all
 * masks are NULL.
 *
 *  @author Ross Harman, MHPCC
 *
 *  XXX: I added the CELL.TRIMSEC region code but there are not tests for it.
 *
 *  @version $Revision: 1.1 $ $Name: not supported by cvs2svn $
 *  @date $Date: 2007-06-19 18:28:38 $
 *
 *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
 */
#include <stdio.h>
#include <string.h>
#include <pslib.h>
#include <psmodules.h>
#include "tap.h"
#include "pstap.h"
#define BADFLAT 0

#define CREATE_AND_SET_IMAGE(NAME,TYPE,VALUE,NROWS,NCOLS)                                                    \
psImage *NAME = (psImage*)psImageAlloc(NCOLS,NROWS,PS_TYPE_##TYPE);                                          \
for(int i=0; i<NAME->numRows; i++) {                                                                         \
    for(int j=0; j<NAME->numCols; j++) {                                                                     \
        NAME->data.TYPE[i][j] = VALUE;                                                                       \
    }                                                                                                        \
}


void testFlatField()
{
    // Test A - Divide input image by flat image
    CREATE_AND_SET_IMAGE(inImage,F64,6.0,3,3)
    pmReadout *inReadout = pmReadoutAlloc(NULL);
    inReadout->image = inImage;
    inReadout->row0 = 0;
    inReadout->col0 = 0;
    CREATE_AND_SET_IMAGE(inMask, U8, 0, 3,3);
    inReadout->mask = inMask;
    CREATE_AND_SET_IMAGE(flatImage1,F64,2.0,3,3)
    pmReadout *flatReadout = pmReadoutAlloc(NULL);
    flatReadout->row0 = 0;
    flatReadout->col0 = 0;
    flatReadout->image = flatImage1;
    if ( !pmFlatField(inReadout, flatReadout, BADFLAT) ) {
        psError(PS_ERR_UNKNOWN,true,"Test A - Returned false should be true");
        return;
    }


    // Test B - Mask flat image data
    CREATE_AND_SET_IMAGE(flatImage2,F64,0.0,3,3)
    flatReadout->image = flatImage2;
    if ( !pmFlatField(inReadout, flatReadout, BADFLAT) ) {
        psError(PS_ERR_UNKNOWN,true,"Test B - Returned false should be true");
        return;
    }


    // Test C - Mask flat image data starting with non-null mask
    flatImage2->data.F64[0][0] = 3.0;
    flatImage2->data.F64[0][1] = -3.0;
    CREATE_AND_SET_IMAGE(mask1,U8,0,3,3);
    psFree(inReadout->mask);
    inReadout->mask = mask1;
    if ( !pmFlatField(inReadout, flatReadout, BADFLAT) ) {
        psError(PS_ERR_UNKNOWN,true,"Test C - Returned false should be true");
        return;
    }


    // Test D - Attempt to use null flat readout
    if( pmFlatField(inReadout, NULL, BADFLAT) ) {
        psError(PS_ERR_UNKNOWN,true,"Test D - Returned true should be false");
        return;
    }



    // Test E - Attempt to use null input image
    psImage *temp = inReadout->image;
    inReadout->image = NULL;
    if ( pmFlatField(inReadout, flatReadout, BADFLAT) ) {
        psError(PS_ERR_UNKNOWN,true,"Test E - Returned true should be false" );
        return;
    }
    inReadout->image = temp    ;



    // Test F - Attempt tp use null flat image
    temp = flatReadout->image;
    flatReadout->image = NULL;
    if ( pmFlatField(inReadout, flatReadout, BADFLAT) ) {
        psError(PS_ERR_UNKNOWN,true,"Test F - Returned true should be false" );
        return;
    }
    flatReadout->image = temp;



    // Test G - Attempt to use input image bigger than flat image
    CREATE_AND_SET_IMAGE(smallFlat,F64,0.0,2,2);
    temp = flatReadout->image;
    flatReadout->image = smallFlat;
    if ( pmFlatField(inReadout, flatReadout, BADFLAT) ) {
        psError(PS_ERR_UNKNOWN,true,"Test G - Returned true should be false");
        return;
    }
    flatReadout->image = temp;



    // Test H - Attempt to use input image mask bigger than flat image
    CREATE_AND_SET_IMAGE(largeMask,F64,0.0,5,5);
    inReadout->mask = largeMask;
    if ( pmFlatField(inReadout, flatReadout, BADFLAT) ) {
        psError(PS_ERR_UNKNOWN,true,"Test H - Returned true should be false");
        return;
    }
    inReadout->mask = mask1;



    // Test I - Attempt to use offset greater than input image
    *(int*)&inReadout->col0 = 50;
    *(int*)&inReadout->row0 = 50;
    if ( pmFlatField(inReadout, flatReadout, BADFLAT) ) {
        psError(PS_ERR_UNKNOWN,true,"Test I - Returned true should be false");
        return;
    }
    *(int*)&inReadout->col0 = 0;
    *(int*)&inReadout->row0 = 0;



//    // Test J - Attempt to use complex input image
//    *(psElemType* ) & inReadout->image->type.type = PS_TYPE_C64;
//    if ( pmFlatField(inReadout, flatReadout, BADFLAT) ) {
//        psError(PS_ERR_UNKNOWN,true,"Test J - Returned true should be false");
//        return;
//    }
//    *(psElemType* ) & inReadout->image->type.type = PS_TYPE_F64;



//    // Test K - Attempt to use complex flat image
//    *(psElemType* ) & flatReadout->image->type.type = PS_TYPE_C64;
//    if ( pmFlatField(inReadout, flatReadout, BADFLAT) ) {
//        psError(PS_ERR_UNKNOWN,true,"Test K - Returned ture should be false");
//        return;
//    }
//    *(psElemType* ) & flatReadout->image->type.type = PS_TYPE_F64;


    // Test L - Attempt to use non-equal input and flat image types
    *(psElemType* ) & flatReadout->image->type.type = PS_TYPE_F32;
    if ( pmFlatField(inReadout, flatReadout, BADFLAT) ) {
        psError(PS_ERR_UNKNOWN,true,"Test L - Returned true should be false");
        return;
    }
    *(psElemType* ) & flatReadout->image->type.type = PS_TYPE_F64;


    // Test M - Attempt to use non-mask type mask image
    *(psElemType* ) & inReadout->mask->type.type = PS_TYPE_F32;
    if ( pmFlatField(inReadout, flatReadout, BADFLAT) ) {
        psError(PS_ERR_UNKNOWN,true,"Test M - Returned true should be false");
        return;
    }
    *(psElemType* ) & inReadout->mask->type.type = PS_TYPE_MASK;


    // Free memory
    psFree(inReadout);
    psFree(flatReadout);
    //psFree(inImage);
    psFree(flatImage1);
    //psFree(flatImage1);
    psFree(smallFlat);
    psFree(largeMask);
}

int main(int argc, char* argv[])
{
    psLogSetFormat("HLNM");
    psLogSetLevel(PS_LOG_INFO);
    plan_tests(20);

    testFlatField();
}


