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

#include "LcmSyslogBridge.h"
#include <vector>


LcmSyslogBridge::LcmSyslogBridge( Component* owner, const Str& channel, lcm::LCM* lcm, short sourceID )
    : LcmListener( channel, lcm, sourceID ),
      owner_( owner ),
      debug_( false )
{}

LcmSyslogBridge::~LcmSyslogBridge()
{}

/// Handle incoming messages on LCM channel
void LcmSyslogBridge::handleMessage( const lcm::ReceiveBuffer *rbuf,
                                     const std::string &chan,
                                     const TethysLcmTypes::LrauvLcmMessage *msg )
{
    if( debug_ ) owner_->getLogger().syslog( "Recived LCM message on channel " + Str( chan.c_str() ) + ".", Syslog::INFO );

    if( sourceID_ == ANY_SOURCE || sourceID_ == msg->source )
    {
        // Decode the message
        unpackMsg( msg );

        std::vector<const char*> names = msg_.listNames();

        for( size_t i = 0; i < names.size(); ++i )
        {
            const TethysLcmTypes::StringArray* syslogArray = msg_.getStringArray( names[i] );

            if( syslogArray != NULL )
            {
                // Extract and post BSD syslog messages
                processSyslogEntrys( syslogArray );
            }
        }
    }
}

void LcmSyslogBridge::processSyslogEntrys( const TethysLcmTypes::StringArray* syslogEntry )
{
    // Extract the syslog severity from the byte array's unit member
    Syslog::Severity severity = Syslog::StringToSeverity( syslogEntry->name.c_str() );

    // Is this StringVector a syslog entry?
    if( severity != Syslog::NONE )
    {
        for( short i = 0; i < syslogEntry->size; ++i )
        {
            // Post syslog messages for severity level
            Str syslogStr( syslogEntry->data[i].c_str() );
            postSyslogEntry( syslogStr, severity );
        }
    }
}


/// Post syslog messages sent from the BSD to LRAUV syslog
void LcmSyslogBridge::postSyslogEntry( Str& syslog_entry, Syslog::Severity severity )
{
    switch( severity )
    {
    case Syslog::CRITICAL:
        if( owner_->isFailureMissionCritical() )
        {
            owner_->getLogger().syslog( syslog_entry, severity );
            owner_->setFailure( FailureMode::DATA );
            break;
        }
        else
        {
            // Component isn't mission critical, so post as a fault
            syslog_entry = "CRITICAL: " + syslog_entry;
            severity = Syslog::FAULT;
            // no break
        }

    case Syslog::FAULT:
        owner_->getLogger().syslog( syslog_entry, severity );
        owner_->setFailure( FailureMode::DATA );
        break;

    case Syslog::IMPORTANT:
    case Syslog::ERROR:
    case Syslog::INFO:
    case Syslog::DEBUG:
        owner_->getLogger().syslog( syslog_entry, severity );
        break;

    default:
        break;
    }
}
