/** \file
 *
 *  Contains the SendDirect class implementation.
 *
 *  Copyright (c) 2007,2008,2009 MBARI
 *  MBARI Proprietary Information.  All Rights Reserved
 */
#include "SendDirect.h"
#include "SendDirectIF.h"

#include "data/DataWriter.h"
#include "data/Slate.h"
#include "logger/DataEntry.h"
#include "missionScript/MissionItem.h"
#include "missionScript/MissionNode.h"
#include "missionScript/ValueClause.h"
#include "supervisor/SendData.h"
#include "supervisor/Supervisor.h"
#include "units/UnitRegistry.h"

SendDirect::SendDirect( const Str& prefix, const Module* module )
    : Behavior( prefix + SendDirectIF::NAME, module, true, true ),
      initialized_( false ),
      destTypeSettingReader_( newSettingReader( SendDirectIF::DEST_TYPE_SETTING ) ),
      destIdSettingReader_( newSettingReader( SendDirectIF::DEST_ID_SETTING ) ),
      destNameSettingReader_( newSettingReader( SendDirectIF::DEST_NAME_SETTING ) ),
      valueSettingReader_( newSettingReader( SendDirectIF::VALUE_SETTING ) ),
      unitSettingReader_( newSettingReader( SendDirectIF::UNIT_SETTING ) ),
      destSetting_( Str::EMPTY_STR ),
      destination_( NULL ),
      unitSetting_( NULL )
{}

SendDirect::~SendDirect()
{
    // shorelogParts_ takes care of itself
}

void SendDirect::initialize()
{
    readConfig();
    //printf( "In initialize, initialized_=%d\n", initialized_ );
}

void SendDirect::run()
{
    runIfUnsatisfied();
}

bool SendDirect::runIfUnsatisfied()
{

    if( initialized_ && NULL != unitSetting_ )
    {
        Timestamp now( Timestamp::Now() );
        double value;

        if( NULL != destination_ && valueSettingReader_->read( *unitSetting_, value ) )
        {
            Double* dv = new Double( *unitSetting_, value );
            SendDestination* dest = new SendDestination( *destination_ );
            SendData::Push( dest, dv, unitSetting_, true );
        }
    }
    return true;
}

void SendDirect::uninitialize()
{
    initialized_ = false;
}

void SendDirect::readConfig()
{
    if( !initialized_
            || destTypeSettingReader_->wasTouchedSinceLastRun( this )
            || destIdSettingReader_->wasTouchedSinceLastRun( this )
            || destNameSettingReader_->wasTouchedSinceLastRun( this ) )
    {
        StrValue destType, destName;
        int destId;
        initialized_ = destTypeSettingReader_->read( destType )
                       && destIdSettingReader_->read( Units::ENUM, destId )
                       && destNameSettingReader_->read( destName );
        delete destination_;
        if( initialized_ )
        {
            destSetting_ = destType.asString() + ":" + destId + ":" + destName.asString();
            destination_ = new SendDestination( destSetting_, true, logger_, Syslog::CRITICAL );
        }
        else
        {
            destination_ = NULL;
            logger_.syslog( "Improperly configured destination type, id, or name", Syslog::CRITICAL );
        }
    }
    if( unitSetting_ == NULL || unitSettingReader_->wasTouchedSinceLastRun( this ) )
    {
        StrValue unitStr;
        if( unitSettingReader_->read( unitStr ) )
        {
            unitSetting_ = UnitRegistry::FindUnit( unitStr.asString() );
        }
        else
        {
            unitSetting_ = NULL;
        }
        if( NULL == unitSetting_ )
        {
            logger_.syslog( "Invalid units setting", Syslog::CRITICAL );
        }
    }
}

/// Mission Component factory interface
Behavior* SendDirect::CreateBehavior( const Str& prefix, const Module* module )
{
    return new SendDirect( prefix, module );
}
