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

#ifndef MISSIONSTACK_H_
#define MISSIONSTACK_H_

#include "component/ComponentRegistry.h"
#include "component/Behavior.h"
#include "logger/Logger.h"
#include "missionScript/MissionItem.h"
#include "process/PCaller.h"

class Assign;
class MissionNode;

/** \ingroup missionScript
 *
 * Collections of Behaviors (including other Aggregates) that
 * make up a larger Behavior within a mission.
 */
class Aggregate : public Behavior
{
public:

    /// Destructor
    virtual ~Aggregate();

    /// Converts table/function at the indicated node to a
    /// Aggregate instance
    static Aggregate* Instance( const Str& name, MissionNode* node, Logger& logger );

    /// Standard component init code
    virtual void initialize();

    /// Called when the mission component becomes preempted.
    void preempted();

    /// Standard component uninit code
    virtual void uninitialize();

    /// Causes a run with no metrics
    virtual void execute()
    {
        run();
    };

    /// Returns true if the aggregate contains an active preemptive clause
    bool containsPreemptive();

    /// Display the currently running stack to Syslog
    void logStack( int& priority );

    /// The actual "payload" of the component
    virtual void run();

    /// Sets the index within parent aggregate
    void setIndex( const int index )
    {
        index_ = index;
    }

    MissionItem* getItemByRefId( const Str& refId );

    void setRef( MissionItem* ref )
    {
        ref_ = ref;
    }

    MissionItem* getRef()
    {
        return ref_;
    }

    // Set output to true if this is a DefineOutput
    void defineArg( const Str& argName, DataValue* dataValue, bool output );

    void redefineArg( const Str& argName, ValueClause* valueClause );

    void setParallel( bool parallel )
    {
        this->parallel_ = parallel;
    }

    MissionItem* getChild( const Str& childName );

    void setResumeItem( MissionItem* resumeItem )
    {
        resumeItem_ = resumeItem;
    }

protected:

    /// Update activeItem_ with the next behavior in the aggregate
    void gotoNextItem();

    /// Behavior list
    FlexArray<MissionItem*> behaviors_;

    /// Alternate "reference" item
    MissionItem* ref_;

    /// Currently active item
    MissionItem* activeItem_;

    /// Item to make active when mission is resumed
    MissionItem* resumeItem_;

    /// Index within parent aggregate
    int index_;

    /// Flag for parallel aggregates
    bool parallel_;

    /// Number of children that are non-parallel
    int nonParallelChildren_;

    /// List of defined args
    FastMap<const Str, DataReader*>* argMap_;

    /// Returns the reader for a defined arg
    DataReader* findArgReader( const Str& argName );

    /// List of Assign elements used for redefining Args
    FlexArray<Assign*>* redefines_;

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

    friend class MissionItem;

    /// Normal Private Constructor
    Aggregate( const Str& name );

    /// Adds a MissionItem to the aggregate
    void push( MissionItem* item );

};

#endif /*MISSIONSTACK_H_*/
