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

#include "data/DataValue.h"
#include "utils/NetCdf.h"

// lookup table that indicates #of bytes for each NetCdfType
unsigned int NetCdf::NetCdfTypeSize_[NC_DOUBLE + 1] = {0, 1, 1, 2, 4, 4, 8 };

/// Constructor
NetCdf::NetCdfVar::NetCdfVar()
    : varId_( -1 ),
      nDims_( 0 ),
      dimIds_( NULL ),
      isRecord_( false ),
      netCdfType_( NC_ABSENT_TYPE ),
      varIndex_( 0 ),
      dataValue_( NULL ),
      numRecs_( 0 ),
      ncId_( -1 )
{}

/// Destructor
NetCdf::NetCdfVar::~NetCdfVar()
{
    if( NULL != dimIds_ )
    {
        delete[] dimIds_;
    }
    while( atts_.size() > 0 )
    {
        NetCdfAtt * netCdfAtt = atts_.popIndexed( atts_.size() - 1 );
        delete netCdfAtt;
    }
    if( NULL != dataValue_ )
    {
        delete dataValue_;
    }
}

/// Destructor
NetCdf::~NetCdf()
{
    if( ncId_ != -1 )
    {
        nc_close( ncId_ );
    }

    // Dims deleted by dimArray_ destructor
    // Delete Global Attributes
    while( gatts_.size() > 0 )
    {
        NetCdfAtt * netCdfAtt = gatts_.popIndexed( gatts_.size() - 1 );
        delete netCdfAtt;
    }
    // Vars deleted by varArray_ destructor
}

/// Finds a dimension by name
/// Returns NULL if error.
NetCdf::NetCdfDim* NetCdf::findDim( const Str& name )
{
    return findDim( dims_, name );
}

/// Finds a global attribute by name
/// Returns NULL if error.
NetCdf::NetCdfAtt* NetCdf::findAtt( const Str& name )
{
    return findAtt( gatts_, name );
}

/// Finds a variable by name
/// Returns NULL if error.
NetCdf::NetCdfVar* NetCdf::findVar( const Str& name )
{
    return findVar( vars_, name );
}

/// Finds a variable's attribute by name
/// Returns NULL if error.
NetCdf::NetCdfAtt* NetCdf::findAtt( NetCdfVar& var, const Str& name )
{
    return findAtt( var.atts_, name );
}

const char* NetCdf::status()
{
    return nc_strerror( status_ );
}

/// Protected Constructor
NetCdf::NetCdf()
    : status_( 0 ),
      ncId_( -1 ),
      dimArray_( true, 4, NC_MAX_DIMS ),
      dims_(),
      gatts_(),
      varArray_( true, 8, NC_MAX_VARS ),
      vars_()
{}

/// Finds a dimension by name in the set of NetCdfDims
/// Returns NULL if error.
NetCdf::NetCdfDim* NetCdf::findDim( NetCdfDims& dims, const Str& name )
{
    return dims.get( name );
}

/// Finds a global attribute by name in the set of NetCdfAtts
/// Returns NULL if error.
NetCdf::NetCdfAtt* NetCdf::findAtt( NetCdfAtts& atts, const Str& name )
{
    return atts.get( name );
}

/// Finds a variable by name in the set of NetCdfVars
/// Returns NULL if error.
NetCdf::NetCdfVar* NetCdf::findVar( NetCdfVars& vars, const Str& name )
{
    return vars.get( name );
}

