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

#include "Logger.h"

#include <errno.h>

#include "data/DataElement.h"
#include "data/Slate.h"
#include "component/Component.h"
#include "logger/DataEntry.h"
#include "logger/EventEntry.h"
#include "logger/LogQueue.h"
#include "logger/SyslogEntry.h"

Timestamp Logger::CriticalErrorReceived_( Timestamp::NOT_SET_TIME );

/// Constructor takes a "facility" name.  Used to tag all subsequent log
/// entries.
///
/// \param facilityIn Name of module for use in logs.
Logger::Logger( const char *facilityIn )
    : LoggerBase( Slate::GetCodedName( facilityIn ) )
{}

/// Constructor takes a "facility" name.  Used to tag all subsequent log
/// entries.
///
/// \param facilityIn Name of module for use in logs.
Logger::Logger( const Str &facilityIn )
    : LoggerBase( Slate::GetCodedName( facilityIn ) )
{}

/// Protected Constructor for use by Slate
Logger::Logger( const CodedStr* facilityIn )
    : LoggerBase( *facilityIn )
{}

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

// The generic "put this entry in the queue"
void Logger::log( LogEntry *entry )
{
    if( entry != NULL )
    {
        LogQueue::Instance().push( entry );
        if( entry->getType() == LogEntry::SYSLOG_LOG_ENTRY )
        {
            SyslogEntry* syslogEntry = static_cast<SyslogEntry*>( entry );
            if( Syslog::CRITICAL == syslogEntry->getSeverity() )
            {
                CriticalErrorReceived_ = entry->getTimestamp();
            }
        }
    }
}

/// Create a syslog entry, push into queue
void Logger::syslog( const Str& msg, Syslog::Severity sev, Service::ServiceType serviceType )
{
    log( new SyslogEntry( msg, sev, facility_, Timestamp::NOT_SET_TIME, serviceType ) );
}

/// Create a new EventEntry for setting a DataElement's accuracy
void Logger::logSetAccuracy( Component* component, DataElement* dataElement )
{
    log( new EventEntry( component, dataElement, EventEntry::SET_DATA_ACCURACY ) );
}

/// Create a new EventEntry for a Component load/unload
void Logger::logComponentLoad( Component* component, const bool loaded )
{
    log( new EventEntry( component, loaded ) );
}

/// Create a new EventEntry for a (Mission)Component run
void Logger::logComponentRun( Component* component, const short loop )
{
    log( new EventEntry( component, loop ) );
}

/// Create a new EventEntry for a Component failure
void Logger::logComponentFailure( Component* component, const FailureMode::FailType failure,
                                  const int failCount )
{
    log( new EventEntry( component, failure, failCount ) );
}

void Logger::logData( DataAccessor &accessor, bool changed )
{
    log( new DataEntry( &accessor, accessor.getElement().isBest(), changed ) );
}

