/*****************************************************************************
   This routine must ensure that the psImageStats() routine can correctly
   call the psVectorStats() routine.  Since the psVectorStats() will be
   thouroughly tested elsewhere, we will only test psImageStats() with
   the PS_STAT_SAMPLE_MEAN here.
*****************************************************************************/
#include <stdio.h>
#include "pslib.h"
#include "psTest.h"
#include "psMemory.h"
#include "psImage.h"
#include "psImageStats.h"
#define NUM_BINS 20
#define N 32
#define M 64

psS32 main()
{
    psStats * myStats = NULL;
    psStats *myStats2 = NULL;
    psImage *tmpImage = NULL;
    psImage *tmpMask = NULL;
    psS32 testStatus = true;
    psS32 memLeaks = 0;
    psS32 nb = 0;
    psS32 i = 0;
    psS32 j = 0;
    psS32 IMAGE_X_SIZE = 0;
    psS32 IMAGE_Y_SIZE = 0;
    psS32 currentId = 0;

    currentId = psMemGetId();
    for ( nb = 0;nb < 6;nb++ ) {
        if ( nb == 0 ) {
            IMAGE_X_SIZE = 1;
            IMAGE_Y_SIZE = 1;
        }
        if ( nb == 1 ) {
            IMAGE_X_SIZE = 1;
            IMAGE_Y_SIZE = N;
        }
        if ( nb == 2 ) {
            IMAGE_X_SIZE = N;
            IMAGE_Y_SIZE = 1;
        }
        if ( nb == 3 ) {
            IMAGE_X_SIZE = N;
            IMAGE_Y_SIZE = N;
        }
        if ( nb == 4 ) {
            IMAGE_X_SIZE = N;
            IMAGE_Y_SIZE = M;
        }
        if ( nb == 5 ) {
            IMAGE_X_SIZE = M;
            IMAGE_Y_SIZE = N;
        }
        printf( "*******************************\n" );
        printf( "* IMAGE SIZE is (%d by %d)\n", IMAGE_X_SIZE, IMAGE_Y_SIZE );
        printf( "*******************************\n" );

        /*************************************************************************/
        /*  Allocate and initialize data structures                      */
        /*************************************************************************/
        tmpImage = psImageAlloc( IMAGE_X_SIZE, IMAGE_Y_SIZE, PS_TYPE_F32 );

        for ( i = 0;i < tmpImage->numRows;i++ ) {
            for ( j = 0;j < tmpImage->numCols;j++ ) {
                tmpImage->data.F32[ i ][ j ] = ( float ) ( i + j );
            }
        }
        tmpMask = psImageAlloc( IMAGE_X_SIZE, IMAGE_Y_SIZE, PS_TYPE_U8 );
        for ( i = 0;i < tmpMask->numRows;i++ ) {
            for ( j = 0;j < tmpMask->numCols;j++ ) {
                if ( ( i > ( tmpMask->numRows / 2 ) ) &&
                        ( j > ( tmpMask->numCols / 2 ) ) ) {
                    tmpMask->data.U8[ i ][ j ] = 1;
                } else {
                    tmpMask->data.U8[ i ][ j ] = 0;
                }
            }
        }

        myStats = psStatsAlloc( PS_STAT_SAMPLE_MEAN );
        /*************************************************************************/
        /*  Calculate Sample Mean with no mask                           */
        /*************************************************************************/
        printPositiveTestHeader( stdout,
                                 "psImageStats functions",
                                 "Calculate Sample Mean, no mask %d" );
        psStats* tmpStats = myStats;
        myStats = psImageStats( myStats, tmpImage, NULL, 0 );
        if ( myStats != tmpStats ) {
            printf("ERROR: input psStats not equal to return psStats\n");
            psAbort(__func__,"Failed input psStats equal to returned psStats");
        }
        printf( "The sample mean was %.2f\n", myStats->sampleMean );

        psMemCheckCorruption( 1 );

        printFooter( stdout,
                     "psImageStats functions",
                     "Calculate Sample Mean, no mask",
                     testStatus );

        /*************************************************************************/
        /*  Calculate Sample Mean with mask                              */
        /*************************************************************************/
        printPositiveTestHeader( stdout,
                                 "psImageStats functions",
                                 "Calculate Sample Mean with mask" );

        myStats = psImageStats( myStats, tmpImage, tmpMask, 1 );
        printf( "The sample mean was %.2f\n", myStats->sampleMean );

        psMemCheckCorruption( 1 );

        printFooter( stdout,
                     "psImageStats functions",
                     "Calculate Sample Mean with mask",
                     testStatus );

        /*************************************************************************/
        /*  Deallocate data structures                                   */
        /*************************************************************************/
        printPositiveTestHeader( stdout,
                                 "psImageStats functions",
                                 "Deallocate the psStats/psImage structure." );
        psFree( myStats );
        psFree( tmpImage );
        psFree( tmpMask );

        psMemCheckCorruption( 1 );
        memLeaks = psMemCheckLeaks(currentId,NULL,stderr,false);
        if ( 0 != memLeaks ) {
            psAbort( __func__, "Memory Leaks! (%d leaks)", memLeaks );
        }

        printFooter( stdout,
                     "psImageStats functions",
                     "Deallocate the psStats/psImage structure.",
                     testStatus );
    }

    /*************************************************************************/
    /*  Test With Various Null Inputs                                        */
    /*************************************************************************/
    printPositiveTestHeader( stdout,
                             "psImageStats functions",
                             "Test With Various Null Inputs" );

    tmpImage = psImageAlloc( IMAGE_X_SIZE, IMAGE_Y_SIZE, PS_TYPE_F32 );
    tmpMask = psImageAlloc( IMAGE_X_SIZE, IMAGE_Y_SIZE, PS_TYPE_U8 );
    myStats = psStatsAlloc( 0 );

    myStats2 = psImageStats( myStats, NULL, NULL, 0 );
    if ( myStats2 != NULL ) {
        printf( "ERROR: myStats2 = psImageStats(myStats, NULL, NULL, 0) != NULL\n" );
    }

    myStats2 = psImageStats( NULL, tmpImage, NULL, 0 );
    if ( myStats2 != NULL ) {
        printf( "ERROR: myStats2 = psImageStats(NULL, tmpImage, NULL, 0) != NULL\n" );
    }

    myStats2 = psImageStats( myStats, tmpImage, NULL, 0 );

    psFree( myStats );
    psFree( tmpImage );
    psFree( tmpMask );

    psMemCheckCorruption( 1 );
    memLeaks = psMemCheckLeaks(currentId,NULL,stderr,false);
    if ( 0 != memLeaks ) {
        psAbort( __func__, "Memory Leaks! (%d leaks)", memLeaks );
    }

    tmpImage = psImageAlloc( IMAGE_X_SIZE, IMAGE_Y_SIZE, PS_TYPE_F32);
    tmpMask = psImageAlloc( IMAGE_X_SIZE, IMAGE_Y_SIZE, PS_TYPE_U32);
    myStats = psStatsAlloc( PS_STAT_SAMPLE_MEAN );
    myStats2 = psImageStats( myStats, tmpImage, tmpMask, 0 );
    if ( myStats2 != NULL ) {
        printf( "ERROR: psImageStats did not return null when mask is invalid type.\n");
    }
    psFree(tmpImage);
    psFree(tmpMask);
    psFree(myStats);
    psMemCheckCorruption(1);
    memLeaks = psMemCheckLeaks(currentId,NULL,stderr,false);
    if( memLeaks != 0 ) {
        psAbort(__func__, "Memory Leaks! (%d leaks)", memLeaks);
    }

    printFooter( stdout,
                 "psImageStats functions",
                 "Test With Various Null Inputs",
                 testStatus );
    return ( !testStatus );
}
