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

#include "DirectoryManagingLogWriter.h"

#include <math.h>

#include "data/ElementURI.h"
#include "data/DataAccess.h"
#include "data/DataValue.h"
#include "data/Slate.h"
#include "logger/DirectoryEntry.h"
#include "logger/DataEntry.h"
#include "logger/SyslogEntry.h"
#include "utils/Mutex.h"
#include "units/Units.h"

DirectoryManagingLogWriter::DirectoryManagingLogWriter( LogWriter& outputTo )
    : LogWriter(),
      outputTo_( outputTo ),
      nameWrites_( false ),
      elementWrites_( false )
{
}

DirectoryManagingLogWriter::~DirectoryManagingLogWriter()
{
}

unsigned int DirectoryManagingLogWriter::writeHeader()
{
    return outputTo_.writeHeader();
}

unsigned int DirectoryManagingLogWriter::writeFooter()
{
    return outputTo_.writeFooter();
}

unsigned int DirectoryManagingLogWriter::write( const LogEntry* entry, const Unit* unit )
{
    if( NULL == entry )
    {
        return 0;
    }
    unsigned int bytesWritten( 0 );
    switch( entry->getType() )
    {
    case LogEntry::DATA_LOG_ENTRY:
        bytesWritten += writeData( dynamic_cast<const DataEntry*>( entry ), unit );
        break;
    case LogEntry::SYSLOG_LOG_ENTRY:
        bytesWritten += writeSyslog( dynamic_cast<const SyslogEntry*>( entry ) );
        break;
    default:
        break;
    }
    return bytesWritten;
}

unsigned int DirectoryManagingLogWriter::writeSyslog( const SyslogEntry* syslogEntry )
{
    unsigned int bytesWritten = 0;
    const CodedStr& codedName = syslogEntry->getLoggerFacility();
    if( NULL == nameWrites_[codedName.getCode()] )
    {
        nameWrites_[codedName.getCode()] = ( int* )true;
        DirectoryEntry* nameEntry = new DirectoryEntry( ( CodedStr* )&codedName );
        bytesWritten += outputTo_.write( nameEntry );
        delete nameEntry;
    }
    bytesWritten += outputTo_.write( syslogEntry );

    return bytesWritten;
}

unsigned int DirectoryManagingLogWriter::writeData( const DataEntry* dataEntry, const Unit* unit )
{
    unsigned int bytesWritten = 0;

    unsigned short eCode = dataEntry->getDataAccess()->getElementCode();
    ElementURI* element = Slate::GetElementURI( eCode );
    unsigned short oCode = dataEntry->getDataAccess()->getOwnerCode();
    CodedStr* codedName = Slate::GetName( oCode );
    if( NULL != codedName )
    {
        if( NULL == nameWrites_[oCode] )
        {
            nameWrites_[oCode] = ( int* )true;
            DirectoryEntry* nameEntry = new DirectoryEntry( codedName );
            bytesWritten += outputTo_.write( nameEntry );
            delete nameEntry;
        }
    }
    if( NULL == elementWrites_[eCode] )
    {
        elementWrites_[eCode] = ( int* )true;
        DirectoryEntry* dirEntry = new DirectoryEntry( element );
        bytesWritten += outputTo_.write( dirEntry );
        delete dirEntry;
        dirEntry = new DirectoryEntry( dataEntry->getDataAccess() );
        bytesWritten += outputTo_.write( dirEntry );
        delete dirEntry;
    }

    bytesWritten += outputTo_.write( dataEntry );
    return bytesWritten;
}

void DirectoryManagingLogWriter::resetDirectoryEntries()
{
    for( int i = nameWrites_.getMinIndex(); i <= nameWrites_.getMaxIndex(); ++i )
    {
        nameWrites_[i] = NULL;
    }
    for( int i = elementWrites_.getMinIndex(); i <= elementWrites_.getMaxIndex(); ++i )
    {
        elementWrites_[i] = NULL;
    }
}


