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

#include "LcmMessagingComponent.h"


using namespace lrauv_lcm_tools;


LcmMessagingComponent::LcmMessagingComponent( const Str& name, ComponentType componentType, const Module* module )
    : MessagingComponent( name, componentType, module )
{}

LcmMessagingComponent::LcmMessagingComponent( const Str& name, ComponentType componentType, const Module* module, const DataURI& enableBroadcast )
    : MessagingComponent( name, componentType, module, enableBroadcast )
{}

LcmMessagingComponent::~LcmMessagingComponent()
{
    // Remove all channels
    bool deleteChannles( true );
    lcmMsgMap_.clear( deleteChannles );
}

void LcmMessagingComponent::setChannelName( const Str& channleName )
{
    // set the channel name for all component writers
    for( unsigned i = 0; i < writers_.size(); ++i )
    {
        writers_[i]->setChannelName( channleName );
    }
}

/// Retrieves an LcmMsgWriter matching the channel name key.
/// Creates a new <channel name, LcmMsgWriter> pair with the designated key if not found.
LcmMsgWriter* LcmMessagingComponent::getLcmMsg( const Str& channelName )
{
    LcmMsgWriter* lcmMsg = lcmMsgMap_.get( channelName );

    if( lcmMsg == NULL )
    {
        lcmMsg = new LcmMsgWriter( channelName );
        lcmMsgMap_.put( channelName, lcmMsg );
    }
    return lcmMsg;
}

/// Activates messaging.
/// Creates and populates the LCM channels.
void LcmMessagingComponent::activateMessaging( void )
{
    logger_.syslog( "Activating messaging.", Syslog::INFO );

    // add component writers to LCM channels
    for( unsigned i = 0; i < writers_.size(); ++i )
    {
        const Str& chnl = writers_[i]->getChannelName();

        LcmMsgWriter* lcmMsg = getLcmMsg( chnl );

        if( lcmMsg != NULL )
        {
            const DataElement& element = writers_[i]->getElement();

            // create a data element entry to the LCM channel
            if( !lcmMsg->add( element ) )
            {
                logger_.syslog( "Falied to add data element " + element.getUri() + " to LCM channel " + chnl, Syslog::ERROR );
            }
        }
    }
}

/// Deactivates messaging.
void LcmMessagingComponent::deactivateMessaging( void )
{
    logger_.syslog( "Deactivating messaging.", Syslog::INFO );

    // Remove all channels
    lcmMsgMap_.clear( true );
}

bool LcmMessagingComponent::setMessage( const Str& channel, const DataElement& dataElement )
{
    LcmMsgWriter* lcmMsg = getLcmMsg( channel );

    if( lcmMsg != NULL && lcmMsg->setValue( dataElement ) )
    {
        return true;
    }

    logger_.syslog( "Failed to copy " + dataElement.getUri() + "'s data value to LCM message.", Syslog::ERROR );
    return false;
}

/// Publishes the component's LCM messages
bool LcmMessagingComponent::publish( void )
{
    bool ok( true );
    for( unsigned i = 0; i < lcmMsgMap_.size(); ++i )
    {
        // get the channel name/msg pair
        LcmMsgWriter* lcmMsg = lcmMsgMap_.getIndexed( i );

        if( lcmMsg != NULL )
        {
            // publish channel data
            ok &= lcmMsg->publish();
        }
    }

    return ok;
}

