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

#include "LcmPolicy.h"
#include "DataElement.h"

#include "component/Component.h"

LcmPolicy::LcmPolicy( Str source )
    : access_map_(), logger_( "LcmPolicy." + source )
{
    source_ = source;

}

LcmPolicy::~LcmPolicy()
{
    // release map content memory
    access_map_.clear( true );

}

int LcmPolicy::addChannel( Str channel, LcmPolicy::OFLAGS oflags, LcmPolicy::IFLAGS iflags )
{
    int retval = -1;
    // get channel if it exists
    LcmAccess *access = ( LcmAccess * )access_map_.get( channel, false );
    // if not...
    if( NULL == access )
    {
        // creaate access struct
        access = new LcmAccess;
        // initialize access struct
        memset( access, 0x0, sizeof( LcmAccess ) );

        // store it in the map
        access_map_.put( Str( channel ), access );
        addOut( channel, oflags );
        addIn( channel, iflags );
        retval = 0;
    }// else already exists

    return retval;
}

int LcmPolicy::removeChannel( Str channel )
{
    int retval = -1;
    // get map value object (and remove entry from map)
    LcmAccess *access = ( LcmAccess * )access_map_.get( channel, true );

    if( access != NULL )
    {
        // free item resources
        delete access;
        retval = 0;
    }// else could not find channel
    return retval;
}

int LcmPolicy::addOut( Str channel, LcmPolicy::OFLAGS flags )
{
    int retval = -1;
    LcmAccess *access = ( LcmAccess * )access_map_.get( channel, false );

    if( access )
    {
        access->oflags_ |= ( uint64_t )flags;
        retval = 0;
    }// else could not find channel
    return retval;
}

int LcmPolicy::removeOut( Str channel, LcmPolicy::OFLAGS flags )
{
    int retval = -1;
    LcmAccess *access = ( LcmAccess * )access_map_.get( channel, false );
    if( access )
    {
        access->oflags_ &= ~( uint64_t )flags;
        retval = 0;
    }// else could not find channel
    return retval;
}

int LcmPolicy::setOut( Str channel, LcmPolicy::OFLAGS flags )
{
    int retval = -1;
    LcmAccess *access = ( LcmAccess * )access_map_.get( channel, false );
    if( access )
    {
        access->oflags_ = ( uint64_t )flags;
        retval = 0;
    }// else could not find channel
    return retval;
}

int LcmPolicy::addIn( Str channel, LcmPolicy::IFLAGS flags )
{
    int retval = -1;
    LcmAccess *access = ( LcmAccess * )access_map_.get( channel, false );

    if( access )
    {
        access->iflags_ |= ( uint64_t )flags;
        retval = 0;
    }// else could not find channel
    return retval;
}

int LcmPolicy::removeIn( Str channel, LcmPolicy::IFLAGS flags )
{
    int retval = -1;
    LcmAccess *access = ( LcmAccess * )access_map_.get( channel, false );
    if( access )
    {
        access->iflags_ &= ~( uint64_t )flags;
        retval = 0;
    }// else could not find channel
    return retval;
}

int LcmPolicy::setIn( Str channel, LcmPolicy::IFLAGS flags )
{
    int retval = -1;
    LcmAccess *access = ( LcmAccess * )access_map_.get( channel, false );
    if( access )
    {
        access->iflags_ = ( uint64_t )flags;
        retval = 0;
    }// else could not find channel
    return retval;
}
const Str& LcmPolicy::getSource()
{
    return source_;
}

int LcmPolicy::channelCount()
{
    return access_map_.size();
}

LcmAccess* LcmPolicy::access( Str channel )
{
    return ( LcmAccess * )access_map_.get( channel, false );
}

bool LcmPolicy::pubAllowed( const Str channel, LcmPolicy::OFLAGS flags )
{
    bool test = false;
    bool debug = false;

    LcmAccess *access = ( LcmAccess * )access_map_.get( channel, false );

    if( access )
    {
        if( debug )
        {
            char msg[128] = {0};
            sprintf( msg, "pubAllowed - src[%s] ch[%s] of[0x%llx] if[0x%llx] cf[0x%llx]",
                     source_.cStr(), channel.cStr(),
                     ( long long unsigned int )access->oflags_,
                     ( long long unsigned int )access->iflags_,
                     ( long long unsigned int )flags );
            logger_.syslog( msg, Syslog::ERROR );
        }

        if( ( access->oflags_ & ( uint64_t )flags ) )
        {
            test = true;
        }
    }
    else
    {
        logger_.syslog( "pubAllowed - accessMap NULL for channel " + channel, Syslog::ERROR );
    }// else NULL access or not allowed
    return test;
}

bool LcmPolicy::subAllowed( const Str channel, LcmPolicy::IFLAGS flags )
{
    bool test = false;
    bool debug = false;
    LcmAccess *access = ( LcmAccess * )access_map_.get( channel, false );

    if( access )
    {
        if( debug )
        {
            char msg[128] = {0};
            sprintf( msg, "pubAllowed - src[%s] ch[%s] of[0x%llx] if[0x%llx] cf[0x%llx]",
                     source_.cStr(), channel.cStr(),
                     ( long long unsigned int )access->oflags_,
                     ( long long unsigned int )access->iflags_,
                     ( long long unsigned int )flags );
            logger_.syslog( msg, Syslog::ERROR );
        }
        if( access->iflags_ & ( uint64_t )flags )
        {
            test = true;
        }
    }
    else
    {
        logger_.syslog( "subAllowed - accessMap NULL for channel " + channel, Syslog::ERROR );
    }// else NULL access
    return test;
}
