/*****************************************************************************
    This routine must ensure that PS_STAT_SAMPLE_MEAN is correctly computed
    by the procedure psArrayStats().
 *****************************************************************************/
#include <stdio.h>
#include "pslib.h"
#include "psTest.h"
#define N 10

psS32 main()
{
    psStats *myStats    = NULL;
    psS32 testStatus      = true;
    psS32 globalTestStatus = true;
    psS32 i               = 0;
    psVector *myVector  = NULL;
    psVector *maskVector= NULL;
    float mean          = 0.0;
    float realMeanNoMask   = 0.0;
    float realMeanWithMask = 0.0;
    psS32 count           = 0;
    psS32 currentId       = psMemGetId();
    psS32 memLeaks        = 0;

    /*************************************************************************/
    /*  Allocate and initialize data structures                      */
    /*************************************************************************/
    myStats = psStatsAlloc(PS_STAT_SAMPLE_MEAN);
    myVector = psVectorAlloc(N, PS_TYPE_F32);
    myVector->n = N;
    maskVector = psVectorAlloc(N, PS_TYPE_U8);
    maskVector->n = N;

    mean = 0.0;
    realMeanWithMask = 0.0;
    // Set the appropriate values for the vector data.
    for (i=0;i<N;i++) {
        myVector->data.F32[i] = (float) i;
    }

    // Set the mask vector and calculate the expected maximum.
    for (i=0;i<N;i++) {
        realMeanNoMask+= myVector->data.F32[i];

        if (i < (N/2)) {
            maskVector->data.U8[i] = 0;
            realMeanWithMask+= myVector->data.F32[i];
            count++;
        } else {
            maskVector->data.U8[i] = 1;
        }
    }


    realMeanNoMask /= (float) N;
    realMeanWithMask /= (float) count;

    /*************************************************************************/
    /*  Call psVectorStats() with no vector mask.                    */
    /*************************************************************************/
    printPositiveTestHeader(stdout,
                            "psStats functions",
                            "PS_STAT_SAMPLE_MEAN: no vector mask");

    myStats = psVectorStats(myStats, myVector, NULL, NULL, 0);
    mean = myStats->sampleMean;

    printf("Called psVectorStats() on a vector with no elements masked.\n");
    printf("The expected mean was %f; the calculated mean was %f\n", realMeanNoMask, mean);
    if (mean == realMeanNoMask) {
        testStatus = true;
    } else {
        testStatus = false;
        globalTestStatus = false;
    }
    printFooter(stdout,
                "psVector functions",
                "PS_STAT_SAMPLE_MEAN: no vector mask",
                testStatus);

    /*************************************************************************/
    /*  Call psVectorStats() with vector mask=1.                             */
    /*************************************************************************/
    printPositiveTestHeader(stdout,
                            "psStats functions",
                            "PS_STAT_SAMPLE_MEAN: with vector mask=1");

    myStats = psVectorStats(myStats, myVector, NULL, maskVector, 1);
    mean = myStats->sampleMean;
    printf("Called psVectorStats() on a vector with last N/2 elements masked.\n");
    printf("The expected mean was %f; the calculated mean was %f\n", realMeanWithMask, mean);
    if (mean == realMeanWithMask) {
        testStatus = true;
    } else {
        testStatus = false;
        globalTestStatus = false;
    }

    printFooter(stdout,
                "psVector functions",
                "PS_STAT_SAMPLE_MEAN: with vector mask=1",
                testStatus);

    /*************************************************************************/
    /*  Call psVectorStats() with vector mask=2.                             */
    /*************************************************************************/
    printPositiveTestHeader(stdout,
                            "psStats functions",
                            "PS_STAT_SAMPLE_MEAN: with vector mask=2");

    // Set the mask vector and calculate the expected maximum.
    // Set the mask vector.
    for (i=0;i<N;i++) {
        if (maskVector->data.U8[i] == 1) {
            maskVector->data.U8[i] = 2;
        }
    }

    myStats = psVectorStats(myStats, myVector, NULL, maskVector, 2);
    mean = myStats->sampleMean;
    printf("Called psVectorStats() on a vector with last N/2 elements masked.\n");
    printf("The expected mean was %f; the calculated mean was %f\n", realMeanWithMask, mean);
    if (mean == realMeanWithMask) {
        testStatus = true;
    } else {
        testStatus = false;
        globalTestStatus = false;
    }

    printFooter(stdout,
                "psVector functions",
                "PS_STAT_SAMPLE_MEAN: with vector mask=2",
                testStatus);

    /*************************************************************************/
    /*  Call psVectorStats() with vector mask=3.                             */
    /*************************************************************************/
    printPositiveTestHeader(stdout,
                            "psStats functions",
                            "PS_STAT_SAMPLE_MEAN: with vector mask=3");

    // Set the mask vector and calculate the expected maximum.
    // Set the mask vector.
    for (i=0;i<N;i++) {
        if (maskVector->data.U8[i] == 2) {
            maskVector->data.U8[i] = 3;
        }
    }

    myStats = psVectorStats(myStats, myVector, NULL, maskVector, 3);
    mean = myStats->sampleMean;
    printf("Called psVectorStats() on a vector with last N/2 elements masked.\n");
    printf("The expected mean was %f; the calculated mean was %f\n", realMeanWithMask, mean);
    if (mean == realMeanWithMask) {
        testStatus = true;
    } else {
        testStatus = false;
        globalTestStatus = false;
    }

    printFooter(stdout,
                "psVector functions",
                "PS_STAT_SAMPLE_MEAN: with vector mask=3",
                testStatus);

    /*************************************************************************/
    /*  Call psVectorStats() with NULL inputs.                               */
    /*************************************************************************/

    printPositiveTestHeader(stdout,
                            "psStats functions",
                            "PS_STAT_SAMPLE_MEAN: NULL inputs");

    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message.");
    if( psVectorStats(myStats, NULL, NULL, NULL, 0) != myStats ) {
        psError(PS_ERR_UNKNOWN,true,"psVectorStats did not return stats when input NULL");
        return 10;
    }
    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message.");
    psStats *myStats2 = psVectorStats(NULL, myVector, NULL, NULL, 0);
    if ( myStats2 != NULL ) {
        psError(PS_ERR_UNKNOWN,true,"psVectorStats did not return NULL");
        return 20;
    }
    printFooter(stdout,
                "psVector functions",
                "PS_STAT_SAMPLE_MEAN: NULL inputs",
                testStatus);

    /*************************************************************************/
    /*  Deallocate data structures                                           */
    /*************************************************************************/
    printPositiveTestHeader(stdout,
                            "psStats functions",
                            "psStats(): deallocating memory");

    psFree(myStats);
    psFree(myVector);
    psFree(maskVector);

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

    printFooter(stdout,
                "psVector functions",
                "psStats(): deallocating memory",
                testStatus);

    return (!globalTestStatus);
}
