/** \file
 *
 *  Contains the test cases for the NetCdfReader class
 *
 *  Copyright (c) 2007,2008,2009 MBARI
 *  MBARI Proprietary Information.  All Rights Reserved
 */

#ifndef _NETCDFREADER_TEST_H_
#define _NETCDFREADER_TEST_H_

#ifndef __arm__
#include "utils/NetCdfReader.h"
#endif

#include <cxxtest/TestSuite.h>

/**
 * %Units tests for class NetCdfReader
 *
 * \ingroup utils
 */
class NetCdfReader_Test : public CxxTest::TestSuite
{
public:

    // Constructor/Destructor test
    void testConstructorDestructor( void )
    {
#ifndef __arm__
        NetCdfReader* netCdfReader = NetCdfReader::NewNetCdfReader( "./Resources/NetCdfReader_Test.nc" );

        // Should fail...
        TS_ASSERT_DIFFERS( ( int )( size_t ) netCdfReader, 0 );

        if( NULL != netCdfReader )
        {
            delete netCdfReader;
        }
#endif
    }

    // GetAttsDimsVars test
    void testFindAttsDimsVars( void )
    {
#ifndef __arm__
        NetCdfReader* netCdfReader = NetCdfReader::NewNetCdfReader( "./Resources/NetCdfReader_Test.nc" );

        // Should fail...
        TS_ASSERT_DIFFERS( ( int )( size_t ) netCdfReader, 0 );

        if( NULL != netCdfReader )
        {
            TS_ASSERT( netCdfReader->findDim( "latitude" ) );
            TS_ASSERT( netCdfReader->findDim( "longitude" ) );

            TS_ASSERT( netCdfReader->findAtt( "name" ) );

            NetCdfReader::NetCdfVar* var( netCdfReader->findVar( "distance" ) );
            TS_ASSERT( var );
            if( var )
            {
                TS_ASSERT( netCdfReader->findAtt( *var, "units" ) );
            }

            delete netCdfReader;
        }
#endif
    }

    // Read(String,Att) test
    void testReadStringAtt( void )
    {
#ifndef __arm__
        NetCdfReader* netCdfReader = NetCdfReader::NewNetCdfReader( "./Resources/NetCdfReader_Test.nc" );

        // Should fail...
        TS_ASSERT_DIFFERS( ( int )( size_t ) netCdfReader, 0 );

        if( NULL != netCdfReader )
        {
            Str attString;
            NetCdfReader::NetCdfAtt* att( netCdfReader->findAtt( "name" ) );
            TS_ASSERT( att );
            if( att )
            {
                TS_ASSERT( netCdfReader->readAttStr( attString, att ) );
                TS_ASSERT_EQUALS( attString, "Distance from shore, central California region" );
            }

            NetCdfReader::NetCdfVar* var( netCdfReader->findVar( "distance" ) );
            TS_ASSERT( var );
            if( var )
            {
                att = netCdfReader->findAtt( *var, "units" );
                TS_ASSERT( att );
                if( att )
                {
                    TS_ASSERT( netCdfReader->readAttStr( attString, att ) );
                    TS_ASSERT_EQUALS( attString, "m" );
                }
            }

            delete netCdfReader;
        }
#endif
    }

    // Read(Float,Var,Index1) test
    void testReadFloatVar1D( void )
    {
#ifndef __arm__
        NetCdfReader* netCdfReader = NetCdfReader::NewNetCdfReader( "./Resources/NetCdfReader_Test.nc" );

        // Should fail...
        TS_ASSERT_DIFFERS( ( int )( size_t ) netCdfReader, 0 );

        if( NULL != netCdfReader )
        {
            float theFloat;
            NetCdfReader::NetCdfVar* var( netCdfReader->findVar( "latitude" ) );
            TS_ASSERT( var );
            if( var )
            {
                TS_ASSERT( netCdfReader->read1D( &theFloat, NetCdf::NC_FLOAT_TYPE, *var, 0 ) );
                TS_ASSERT_DELTA( theFloat, 35.0, 1e-4 );
                TS_ASSERT( netCdfReader->read1D( &theFloat, NetCdf::NC_FLOAT_TYPE, *var, 280 ) );
                TS_ASSERT_DELTA( theFloat, 37.8, 1e-4 );
            }
            var = netCdfReader->findVar( "longitude" );
            TS_ASSERT( var );
            if( var )
            {
                TS_ASSERT( netCdfReader->read1D( &theFloat, NetCdf::NC_FLOAT_TYPE, *var, 0 ) );
                TS_ASSERT_DELTA( theFloat, -123.8, 1e-4 );
                TS_ASSERT( netCdfReader->read1D( &theFloat, NetCdf::NC_FLOAT_TYPE, *var, 280 ) );
                TS_ASSERT_DELTA( theFloat, -121.0, 1e-4 );
            }
            var = netCdfReader->findVar( "distance" );
            TS_ASSERT( var );
            if( var )
            {
                TS_ASSERT( netCdfReader->read2D( &theFloat, NetCdf::NC_FLOAT_TYPE, *var, 0, 0 ) );
                TS_ASSERT_DELTA( theFloat, 224.5141, 1e-4 );
            }
            delete netCdfReader;
        }
#endif
    }

    // Read(Float,Var,Index1a,Index1b) test
    void testReadFloatVar1DRange( void )
    {
#ifndef __arm__
        NetCdfReader* netCdfReader = NetCdfReader::NewNetCdfReader( "./Resources/NetCdfReader_Test.nc" );

        // Should fail...
        TS_ASSERT_DIFFERS( ( int )( size_t ) netCdfReader, 0 );

        if( NULL != netCdfReader )
        {
            float theFloats[3];
            NetCdfReader::NetCdfVar* var( netCdfReader->findVar( "longitude" ) );
            TS_ASSERT( var );
            if( var )
            {
                TS_ASSERT( netCdfReader->read1DArray( theFloats, NetCdf::NC_FLOAT_TYPE, *var, 30, 32 ) );
                TS_ASSERT_DELTA( theFloats[0], -123.50, 1e-4 );
                TS_ASSERT_DELTA( theFloats[1], -123.49, 1e-4 );
                TS_ASSERT_DELTA( theFloats[2], -123.48, 1e-4 );
            }
            delete netCdfReader;
        }
#endif
    }

    // ReadFloatVar,Index1,Index2) test
    void testReadFloatVar2D( void )
    {
#ifndef __arm__
        NetCdfReader* netCdfReader = NetCdfReader::NewNetCdfReader( "./Resources/NetCdfReader_Test.nc" );

        // Should fail...
        TS_ASSERT_DIFFERS( ( int )( size_t ) netCdfReader, 0 );

        if( NULL != netCdfReader )
        {
            float theFloat;
            NetCdfReader::NetCdfVar* var( netCdfReader->findVar( "distance" ) );
            TS_ASSERT( var );
            if( var )
            {
                TS_ASSERT( netCdfReader->read2D( &theFloat, NetCdf::NC_FLOAT_TYPE, *var, 0, 0 ) );
                TS_ASSERT_DELTA( theFloat, 224.5141, 1e-4 );
                TS_ASSERT( netCdfReader->read2D( &theFloat, NetCdf::NC_FLOAT_TYPE, *var, 140, 140 ) );
                TS_ASSERT_DELTA( theFloat, 41.8181, 1e-4 );
                TS_ASSERT( netCdfReader->read2D( &theFloat, NetCdf::NC_FLOAT_TYPE, *var, 280, 280 ) );
                TS_ASSERT_DELTA( theFloat, 96.3373, 1e-4 );
            }
            delete netCdfReader;
        }
#endif
    }

    // ReadFloat(Var,Index1a,Index1b,Index2a,Index2b) test
    void testReadFloatVar2DRange( void )
    {
#ifndef __arm__
        NetCdfReader* netCdfReader = NetCdfReader::NewNetCdfReader( "./Resources/NetCdfReader_Test.nc" );
        TS_ASSERT( netCdfReader );

        if( NULL != netCdfReader )
        {
            float theFloats[3][3];
            NetCdfReader::NetCdfVar* var( netCdfReader->findVar( "distance" ) );
            TS_ASSERT( var );
            if( var )
            {
                TS_ASSERT( netCdfReader->read2DArray( theFloats, NetCdf::NC_FLOAT_TYPE, *var, 30, 32, 30, 32 ) );
                TS_ASSERT_DELTA( theFloats[0][0], 182.2367, 1e-4 );
                TS_ASSERT_DELTA( theFloats[0][1], 181.5249, 1e-4 );
                TS_ASSERT_DELTA( theFloats[0][2], 180.8149, 1e-4 );
                TS_ASSERT_DELTA( theFloats[1][0], 181.5502, 1e-4 );
                TS_ASSERT_DELTA( theFloats[1][1], 180.8359, 1e-4 );
                TS_ASSERT_DELTA( theFloats[1][2], 180.1232, 1e-4 );
                TS_ASSERT_DELTA( theFloats[2][0], 180.8680, 1e-4 );
                TS_ASSERT_DELTA( theFloats[2][1], 180.1511, 1e-4 );
                TS_ASSERT_DELTA( theFloats[2][2], 179.4357, 1e-4 );
            }
            delete netCdfReader;
        }
#endif
    }
};

#endif // _NETCDFREADER_TEST_H
