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


#ifndef NETCDFTABLELOGWRITER_H_
#define NETCDFTABLELOGWRITER_H_

#include "data/BinaryDataType.h"
#include "logger/HasFilename.h"
#include "logger/TableLogWriter.h"
#include "utils/NetCdfWriter.h"
#include "utils/Str.h"

class DataValue;

/**
 *  Defines a LogWriter that generates a NetCDF table of values.  A list of
 *  variable names is supplied to the constructor.  If any of these variables
 *  change their value in a computation cycle, then a record is added to the
 *  NetCDF file with the current value of every variable.  The Timestamp for
 *  each record corresponds to the time of the start of the computation cycle
 *  in which any value changed.
 *
 *  \ingroup logging
 */
class NetCdfTableLogWriter : public TableLogWriter, public HasFilename
{
public:

    /// Constructor.
    NetCdfTableLogWriter( const Str& filename, bool version4, int varCount, char** varListt, char** unitList,
                          bool interpolate = false, int attCount = 0, char** attList = NULL );

    /// Destructor.
    virtual ~NetCdfTableLogWriter();

    /// Start writing the NetCDF file
    unsigned int writeHeader();

    /// Write an entry to the buffer.  If a start of cycle is encountered,
    /// write the whole record to the NetCDF file.
    unsigned int write( const LogEntry *entry, const Unit* unit = NULL );

    /// Finish writing the NetCDF file
    unsigned int writeFooter();

    virtual void clearRow();

    virtual const Str& getFilename()
    {
        return filename_;
    }

private:
    // Note that the copy constructor below is private and not given a body.
    // Any attempt to call it will return a compiler error.
    NetCdfTableLogWriter( const NetCdfTableLogWriter& old ); // disallow copy constructor

    /// Initialize variables, etc
    void initializeNetCdfTableLogWriter();

    /// Add a new variable
    void addVar( const int index, const ElementURI* uri, BinaryDataType binaryType, const Unit& unit, short universalCode );

    /// Set an attribute value
    void setAttValue( const DataEntry *dataEntry, const int attIndex );

    /// Write a data item
    unsigned int writeToColumn( const DataEntry *dataEntry, const int column );

    // Write a netcdf record
    unsigned int writeRow();

    /// Initialize the NetCDF file
    void netCdfInitialize();

    const Str filename_;
    int attCount_;
    char** attList_;
    unsigned short* attUriCodes_;
    int* attCodeLookup_;
    NetCdfWriter* netCdfWriter_;
    bool netCdfInitialized_;
    bool finalized_;
    const NetCdf::NetCdfAtt** atts_;
    const NetCdf::NetCdfAtt** attUnits_;
    NetCdf::NetCdfVar** vars_;

};

#endif /*NETCDFTABLELOGWRITER_H_*/
