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

#ifndef NETCDFREADER_H_
#define NETCDFREADER_H_

#include "utils/NetCdf.h"

#include "io/FileInStream.h"

/**
 *  A very compact, very simple netCDF reader with a minimal feature set.
 *
 *  \ingroup utils
 */
class NetCdfReader : public NetCdf
{
public:

    /// Returns an newNetCdfReader of a NetCdfReader for a file
    static NetCdfReader* NewNetCdfReader( const char* fileName );

    /// Destructor
    virtual ~NetCdfReader();

    /// Indicates intialization success
    bool isOk() const
    {
        return ok_;
    }

    /// Reads the value of the variable at the indices as the indicated type
    /// Returns true if no error.
    bool read( void* assignTo, const NetCdfType assignType, const NetCdfVar& var,
               const size_t indices[] );

    /// Reads the value of the variable at the 1D index as the specified type
    /// Returns true if no error.
    bool read1D( void* assignTo, const NetCdfType assignType, const NetCdfVar& var,
                 const unsigned long index1 );

    /// Reads the value of the variable at the 2D index as the specified type
    /// Returns true if no error.
    bool read2D( void* assignTo, const NetCdfType assignType, const NetCdfVar& var,
                 const unsigned long index1, const unsigned long index2 );

    /// Reads the value of the variable at the 3D index as the specified type
    /// Returns true if no error.
    bool read3D( void* assignTo, const NetCdfType assignType, const NetCdfVar& var,
                 const unsigned long index1, const unsigned long index2,
                 const unsigned long index3 );

    /// Reads the value of the variable at the 4D index as the specified type
    /// Returns true if no error.
    bool read4D( void* assignTo, const NetCdfType assignType, const NetCdfVar& var,
                 const unsigned long index1, const unsigned long index2,
                 const unsigned long index3, const unsigned long index4 );

    /// Reads a 1D range of the variable between a pair of indices
    /// (a <= index <= b) into an existing 1D array of the specified type
    /// Returns true if no error.
    bool read1DArray( void* assignTo, const NetCdfType assignType, const NetCdfVar& var,
                      const unsigned long index1a, const unsigned long index1b );

    /// Reads a 2D range of the variable between 2 pairs of indices
    /// (a <= index <= b) into an existing 2D array of the specified type
    /// Returns true if no error.
    bool read2DArray( void* assignTo, const NetCdfType assignType, const NetCdfVar& var,
                      const unsigned long index1a, const unsigned long index1b,
                      const unsigned long index2a, const unsigned long index2b );

    /// Reads a 3D range of the variable between 3 pairs of indices
    /// (a <= index <= b) into an existing 3D array of the specified type
    /// Returns true if no error.
    bool read3DArray( void* assignTo, const NetCdfType assignType, const NetCdfVar& var,
                      const unsigned long index1a, const unsigned long index1b,
                      const unsigned long index2a, const unsigned long index2b,
                      const unsigned long index3a, const unsigned long index3b );

    /// Reads a 4D range of the variable between 4 pairs of indices
    /// (a <= index <= b) into an existing 3D array of the specified type
    /// Returns true if no error.
    bool read4DArray( void* assignTo, const NetCdfType assignType, const NetCdfVar& var,
                      const unsigned long index1a, const unsigned long index1b,
                      const unsigned long index2a, const unsigned long index2b,
                      const unsigned long index3a, const unsigned long index3b,
                      const unsigned long index4a, const unsigned long index4b );

    /// Reads the value of the attribute as a Str
    /// Returns true if no error.
    bool readAttStr( Str& assignTo, const NetCdfAtt* att );

    /// Reads the value of the attribute
    /// Returns true if no error.
    bool readAtt( void* assignTo, const NetCdfType assignType, const NetCdfAtt* att );

    /// Finds the first variable with the indicated attribute name and attribute value
    /// Returns null if no match
    NetCdfVar* findNetCdfVarByAttribute( const Str& name, const Str& value );

protected:

    /// Protected Constructor
    NetCdfReader( const char* fileName );

    /// Opens a NetCdfReader for a file
    /// Returns true if no error.
    bool initialize( const char* fileName );

    bool ok_;
};

#endif /*NETCDFREADER_H_*/
