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

#ifndef METHOD_H_
#define METHOD_H_

#include "data/ElementURI.h"
#include "logger/Logger.h"
#include "utils/FlexArray.h"

class DataReader;
class DataValue;
class DataWriter;
class DefinedBehavior;
class OutputURI;
class ScriptAPI;
class ScriptNode;
class SettingReader;
class Unit;

/**
 *  Information to create a Input in a Method.
 *
 *  \ingroup missionScript
 */
class InputInfo
{
public:
    InputInfo( const Str& name, const Str& uriPart, DataValue* defaultValue )
        : name_( name ),
          uriPart_( uriPart ),
          defaultValue_( defaultValue )
    {}

    virtual ~InputInfo();

    const Str& getName()
    {
        return name_;
    }
    const Str& getUriPart()
    {
        return uriPart_;
    }
    DataValue* getDataValue()
    {
        return defaultValue_;
    }

protected:
    const Str name_;
    const Str uriPart_;
    DataValue* defaultValue_;

private:
    // Note that the copy constructor below is private and not given a body.
    // Any attempt to call it will return a compiler error.
    InputInfo( const InputInfo& old ); // disallow copy constructor
};


/**
 *  Information to create a Output in a Method.
 *
 *  \ingroup missionScript
 */
class OutputInfo
{
public:
    OutputInfo( const ElementURI* uri, const Unit* unit, bool arg )
        : uri_( uri ),
          unit_( unit ),
          arg_( arg )
    {}

    virtual ~OutputInfo()
    {}

    const ElementURI* getUri()
    {
        return uri_;
    }
    const Unit* getUnit()
    {
        return unit_;
    }
    bool isArg()
    {
        return arg_;
    }

protected:
    const ElementURI* uri_;
    const Unit* unit_;
    const bool arg_;

private:
    // Note that the copy constructor below is private and not given a body.
    // Any attempt to call it will return a compiler error.
    OutputInfo( const OutputInfo& old ); // disallow copy constructor
};



class MethodInfo
{
public:
    /// Constructor
    MethodInfo()
        : inputs_( true ),
          outputs_( true )
    {}

    void addInput( InputInfo* input )
    {
        inputs_.push( input );
    }

    void addOutput( OutputInfo* output )
    {
        outputs_.push( output );
    }

    void setScript( const char* methodName, const char* code )
    {
        methodName_ = methodName;
        code_ = code;
    }

protected:

    friend class Method;

    /// Method arguments;
    FlexArray<InputInfo*> inputs_;

    /// Return values for method;
    FlexArray<OutputInfo*> outputs_;

    // Name of method
    Str methodName_;

    /// Code for method;
    Str code_;

private:
    // Note that the copy constructor below is private and not given a body.
    // Any attempt to call it will return a compiler error.
    MethodInfo( const MethodInfo& old ); // disallow copy constructor

};

/**
 *  Wraps the inputs, outputs, and code for a method (i.e., initialize, run, etc)
 *  within a scripted component.
 *
 *  \ingroup missionScript
 */
class Method
{
public:
    /// Constructor
    Method( DefinedBehavior* definedBehavior, MethodInfo* methodInfo, ScriptAPI* scriptAPI );

    virtual ~Method();

    void addInput( DataReader* input, const Unit* unit );

    void addOutput( DataWriter* output, const Unit* unit );

    virtual void execute( Logger& logger );

    virtual bool executeBool( Logger& logger );

    virtual void executeVoid( Logger& logger );

    virtual FlexArray<DataWriter*>& getOutputs()
    {
        return outputs_;
    }

    virtual FlexArray<const Unit*>& getOutUnits()
    {
        return outUnits_;
    }

    virtual FlexArray<OutputURI*>& getOutputArgs()
    {
        return outputArgs_;
    }

protected:
    /// Arguments for method;
    FlexArray<DataReader*> inputs_;

    /// Method arguments;
    FlexArray<SettingReader*>& settings_;

    /// Return values for method;
    FlexArray<DataWriter*> outputs_;

    /// Units of return values for method;
    FlexArray<const Unit*> outUnits_;

    /// Non-null entries indicate outputArgs;
    FlexArray<OutputURI*> outputArgs_;

    /// Code for method;
    ScriptNode* scriptNode_;

private:
    // Note that the copy constructor below is private and not given a body.
    // Any attempt to call it will return a compiler error.
    Method( const Method& old ); // disallow copy constructor

};

#endif /* METHOD_H_ */
