/** \file
 *
 *  Contains the Method and MethodInfo class implementations.
 *
 *  Copyright (c) 2007,2008,2009 MBARI
 *  MBARI Proprietary Information.  All Rights Reserved
 */

#include "Method.h"

#include "data/DataReader.h"
#include "data/DataWriter.h"
#include "data/Slate.h"
#include "missionScript/DefineBehavior.h"
#include "missionScript/ScriptAPI.h"
#include "missionScript/ScriptNode.h"
#include "missionScript/SettingReader.h"

Method::Method( DefinedBehavior* definedBehavior, MethodInfo* methodInfo, ScriptAPI* scriptAPI )
    : inputs_( true ),
      settings_( definedBehavior->getSettings() ),
      outputs_( true ),
      outUnits_( false ),
      outputArgs_( false ),
      scriptNode_( NULL )
{
    for( unsigned int i = 0 ; i < methodInfo->inputs_.size(); ++i )
    {
        InputInfo* input = methodInfo->inputs_.get( i );
        DataReader* inputReader = Slate::NewReader( ElementURI( "", input->getUriPart() ), definedBehavior, input->getDataValue() );
        inputs_.push( inputReader );
    }
    for( unsigned int i = 0 ; i < methodInfo->outputs_.size(); ++i )
    {
        OutputInfo* output = methodInfo->outputs_.get( i );
        const ElementURI* uri = output->getUri();
        const OutputURI* outputURI = dynamic_cast<const OutputURI*>( uri );
        if( NULL != outputURI && output->isArg() )
        {
            outputs_.push( NULL );
            outputArgs_.push( ( OutputURI* )output->getUri() );
        }
        else
        {
            DataWriter* outputWriter = Slate::NewWriter( *output->getUri(), definedBehavior );
            outputs_.push( outputWriter );
            outputArgs_.push( NULL );
        }
        outUnits_.push( output->getUnit() );

    }

    scriptNode_ = scriptAPI->makeScriptFunction( definedBehavior->getName().cStr(), definedBehavior->getName().cStr(),
                  methodInfo->methodName_.cStr(), methodInfo->inputs_, definedBehavior->getDefine()->getSettings(), methodInfo->code_.cStr(), definedBehavior->getLogger() );
}

Method::~Method()
{}

void Method::addInput( DataReader* input, const Unit* unit )
{

}

void Method::addOutput( DataWriter* output, const Unit* unit )
{
    outputs_.push( output );
    outUnits_.push( ( Unit* )unit );
}

void Method::execute( Logger& logger )
{
    if( NULL != scriptNode_ )
    {
        scriptNode_->execute( inputs_, settings_, outputs_, outUnits_, logger );
    }
    else
    {
        logger.syslog( "Called execute with null method", Syslog::CRITICAL );
    }
}

bool Method::executeBool( Logger& logger )
{
    if( NULL != scriptNode_ )
    {
        bool returnValue( true );
        scriptNode_->execute( inputs_, settings_, returnValue, logger );
        return returnValue;
    }
    else
    {
        logger.syslog( "Called executeBool with null method", Syslog::CRITICAL );
        return true;
    }
}

void Method::executeVoid( Logger& logger )
{
    if( NULL != scriptNode_ )
    {
        scriptNode_->execute( logger );
    }
    else
    {
        logger.syslog( "Called executeVoid with null method", Syslog::CRITICAL );
    }
}

InputInfo::~InputInfo()
{
    if( NULL != defaultValue_ )
    {
        delete defaultValue_;
    }
}
