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

#ifndef FILELOGWRITER_H_
#define FILELOGWRITER_H_

#include "io/FileOutStream.h"
#include "logger/HasFilename.h"
#include "logger/LogWriter.h"

class FileEncoder;

/**
 *  Wraps around another LogWriter to write LogEntries to a file
 *
 *  Designed around assumption that it always has a log file open, though
 *  it does keep track of whether the stream is open or close, which it uses
 *  to determine if it's valid.
 *
 *  \ingroup logging
 */
class FileLogWriter: public LogWriter, public HasFilename
{
public:
    enum FlushFreq
    {
        FLUSH_ONCE = 0, FLUSH_PER_CYCLE = 1, FLUSH_PER_WRITE
    };

    /** Constructor with filename & specified flushFreq
     *
     * \param filename Name of  file to write to
     * \param logWriter logWriter that provides input for file logging
     * \param append if true, append to file, otherwise overwrite.
     * \param fileEncoder optional encoder to run whenever the file closes
     */
    FileLogWriter( const Str &filename, LogWriter* logWriter, const bool append =
                       false, FileEncoder* fileEncoder = NULL );

    /** Constructor with FILE
     *
     * \param file FILE to write to
     * \param logWriter logWriter that provides input for file logging
     */
    FileLogWriter( FILE* file, LogWriter* logWriter );

    /// Destructor, closes file if open.
    virtual ~FileLogWriter();

    /// Reset cached input settings
    virtual void resetInputs();

    /// Is the LogWriter valid?
    virtual bool valid( void )
    {
        return isWritable();
    }
    ;

    /// Write
    virtual unsigned int write( const LogEntry *entry, const Unit* unit = NULL );

    /// If flushFreq_ is FLUSH_PER_CYCLE, this causes an output flush
    virtual void endCycle();

    /// Accessors
    unsigned int getBytesInFile( void )
    {
        return bytesInFile_;
    }
    ;

    unsigned int getEntriesWritten( void )
    {
        return entriesWritten_;
    }
    ;

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

    void resetFilename( const Str& filename );

    /// Keep track of whether the stream is open
    bool isWritable( void )
    {
        return fileStream_.isWritable();
    }
    ;

    /*virtual void config( Logger& logger );*/

protected:

    /// Open the stream to the named file
    bool open( const char *filename, const bool append );

    /// Close the currently open file.
    void close( void );

    void setFlushFreq( const FlushFreq flushFreq )
    {
        flushFreq_ = flushFreq;
    }

    FileEncoder* getFileEncoder()
    {
        return fileEncoder_;
    }

    void setFilename( const Str& filename )
    {
        filename_ = filename;
    }

    /// The LogWriter that does the actual writing
    LogWriter* logWriter_;

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

    /// The output file stream.
    FileOutStream fileStream_;

    /// Total entries written
    unsigned int entriesWritten_;

    /// Total bytes written
    unsigned int bytesInFile_;

    /// True if a file name is specified in constructor
    bool initFilename_;

    /// Name of the current file
    Str filename_;

    FlushFreq flushFreq_;

    bool writtenInCycle_;

    FileEncoder* fileEncoder_;

};

#endif /*FILELOGWRITER_H_*/
