/*****************************************************************************
   This routine must ensure that the psHistogram structure is correctly
   allocated and populated by the psImageHistogram() function.
*****************************************************************************/
#include <stdio.h>
#include "pslib.h"
#include "psTest.h"
#include "psMemory.h"
#include "psImage.h"
#include "psImageStats.h"
#define NUM_BINS 20
#define IMAGE_SIZE 20
#define N 32
#define M 64

psS32 main()
{
    psHistogram * myHist = NULL;
    psHistogram *myHist2 = 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 + 0.1 );
            }
        }
        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;
                }
            }
        }

        /*************************************************************************/
        /*  Calculate Histogram with no mask                             */
        /*************************************************************************/
        printPositiveTestHeader( stdout,
                                 "psImageStats functions",
                                 "Calculate Histogram, no mask" );

        myHist = psHistogramAlloc( 0.0, ( float ) ( IMAGE_X_SIZE + IMAGE_Y_SIZE ),
                                   NUM_BINS );
        myHist = psImageHistogram( myHist, tmpImage, NULL, 0 );
        for ( i = 0;i < NUM_BINS;i++ ) {
            printf( "Bin number %d bounds: (%.1f - %.1f) data (%f)\n", i,
                    myHist->bounds->data.F32[ i ],
                    myHist->bounds->data.F32[ i + 1 ],
                    myHist->nums->data.F32[ i ] );
        }
        psFree( myHist );

        psMemCheckCorruption( 1 );
        printFooter( stdout,
                     "psImageStats functions",
                     "Calculate Histogram, no mask",
                     testStatus );

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

        myHist = psHistogramAlloc( 0.0, ( float ) ( IMAGE_X_SIZE + IMAGE_Y_SIZE ),
                                   NUM_BINS );
        myHist = psImageHistogram( myHist, tmpImage, tmpMask, 1 );
        for ( i = 0;i < NUM_BINS;i++ ) {
            printf( "Bin number %d bounds: (%.2f - %.2f) data (%f)\n", i,
                    myHist->bounds->data.F32[ i ],
                    myHist->bounds->data.F32[ i + 1 ],
                    myHist->nums->data.F32[ i ] );
        }

        psMemCheckCorruption( 1 );
        printFooter( stdout,
                     "psImageStats functions",
                     "Calculate Histogram with mask",
                     testStatus );

        /*************************************************************************/
        /*  Deallocate data structures                                   */
        /*************************************************************************/
        printPositiveTestHeader( stdout,
                                 "psImageStats functions",
                                 "Deallocate the psHistogram/psImage structure." );
        psFree( myHist );
        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 psHistogram/psImage structure.",
                     testStatus );
    }
    printPositiveTestHeader( stdout,
                             "psImageStats functions",
                             "Calling psImageHistogram() with NULL parameters" );

    tmpImage = psImageAlloc( IMAGE_X_SIZE, IMAGE_Y_SIZE, PS_TYPE_F32 );
    myHist = psHistogramAlloc( 0.0, ( float ) ( IMAGE_X_SIZE + IMAGE_Y_SIZE ),
                               NUM_BINS );
    myHist2 = psImageHistogram( NULL, tmpImage, NULL, 0 );
    if ( myHist2 != NULL ) {
        printf( "ERROR: myHist2 not equal to NULL\n" );
    }

    myHist2 = psImageHistogram( myHist, NULL, NULL, 0 );
    myHist2 = psImageHistogram( NULL, tmpImage, NULL, 0 );
    if ( myHist2 != NULL ) {
        printf( "ERROR: myHist2 not equal to NULL\n" );
    }


    tmpMask = psImageAlloc( IMAGE_X_SIZE, IMAGE_Y_SIZE, PS_TYPE_S8 );
    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.S8[ i ][ j ] = 1;
            } else {
                tmpMask->data.S8[ i ][ j ] = 0;
            }
        }
    }

    psLogMsg(__func__,PS_LOG_INFO,"Following should be an error for invalid mask type.");
    myHist2 = psImageHistogram(myHist,tmpImage,tmpMask,1);
    if (myHist2 != NULL) {
        printf("ERROR: myHist2 not equal to NULL\n");
    }

    psFree( tmpMask );
    psFree(myHist);
    psFree(myHist2);
    psFree( tmpImage );
    psMemCheckCorruption( 1 );

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

    printFooter( stdout,
                 "psImageStats functions",
                 "Calling psImageHistogram() with NULL parameters",
                 testStatus );

    return ( !testStatus );
}
