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

#include "BinaryLogWriter.h"
#include "io/OutStream.h"
#include "logger/DataEntry.h"
#include "logger/DirectoryEntry.h"

/** Default Constructor
 * Assumes that the stream will be assigned later via setOutStream()
 *
 * \param withDirectory If true, include DirectoryEntry entries.
 */
BinaryLogWriter::BinaryLogWriter( bool withDirectory, bool debug )
    : LogWriter(),
      timeBase_( Timespan::NOT_SET_TIME ),
      withDirectory_( withDirectory ),
      debug_( debug )
{}

/** Constructor, takes an OutStream.
 *
 * \param stream An OutStream for output.
 * \param withDirectory If true, include DirectoryEntry entries.
 */
BinaryLogWriter::BinaryLogWriter( OutStream &stream, bool withDirectory )
    : LogWriter( stream ),
      timeBase_( Timespan::NOT_SET_TIME ),
      withDirectory_( withDirectory ),
      debug_( false )
{}

/// Destructor
BinaryLogWriter::~BinaryLogWriter()
{}

/// Start the binary log
unsigned int BinaryLogWriter::writeHeader()
{
    unsigned int bytesWritten( 0 );

    if( withDirectory_ && NULL != logStream_ && logStream_->isWritable() )
    {
        bytesWritten += DirectoryEntry().write( timeBase_, *logStream_ );
    }

    return bytesWritten;
}

/// This does not actually change units, since binary logs are always in the base unit.
unsigned int BinaryLogWriter::write( const LogEntry *entry, const Unit* unit )
{
    MutexLocker lock( writeMutex_ );

    unsigned int bytesWritten( 0 );

    if( entry != NULL )
    {
        if( debug_ )
        {
            Str output = entry->toString( unit );
            if( output.length() > 0 )
            {
                logStream_->write( output.cStr() );
            }
            if( entry->getType() == LogEntry::DATA_LOG_ENTRY )
            {
                DataEntry* dataEntry = ( DataEntry* )entry;
                DataAccess* dataAccess = dataEntry->getDataAccess();
                DataValue* dataValue = dataEntry->getDataValue();
                logStream_->writeChar( '!' );
                logStream_->writeUShortHex( dataAccess->getBinaryType() );
                logStream_->writeChar( '!' );
                logStream_->writeUShortHex( dataValue->getBinaryType() );
                logStream_->writeChar( '!' );
                if( dataAccess->getBinaryType() != dataValue->getBinaryType() )
                {
                    logStream_->write( "?!?!?|" );
                }
            }
        }
        bytesWritten = entry->write( timeBase_, *logStream_ );
        if( debug_ )
        {
            logStream_->writeChar( '\n' );
        }
    }
    return bytesWritten;
}
