#pragma once
#include "Behavior.h"
#include "../../../../Utils/Process/GroupProcess.h"

/**
 * @brief A group behavior outputs commands to a group of units (possibly by being decomposed
 *        into multiple individual unit behaviors).
 */
class GroupBehavior : public GroupProcess, public virtual Behavior
{
public:
  /**
   * @brief GroupBehavior constructor.
   * @param parent The parent process.
   * @param initialPriority The initial priority of the behavior.
   * @param group The persistent unit group to be used by this behavior.
   */
  GroupBehavior(const Process* parent, unsigned int initialPriority, const PersistentUnitGroup* group)
    : GroupProcess(parent, group)
    , Process(parent)
    , Behavior(parent, initialPriority)
    , FSM(parent)
  {
  }

  /////////
  // GUI //
  /////////
  virtual UnitRecordGroup _getUnitsInvolved() const
  {
    return UnitRecordGroup(getGroup()->begin(), getGroup()->end());
  }

protected:
  virtual void _output(std::ostream& out) const
  {
    Behavior::_output(out);
  }

  /**
   * @brief Called when the group behavior starts.
   */
  virtual void onStart()
  {
    GroupProcess::onStart();
    Behavior::onStart();
  }

  /**
   * @brief Called when the group behavior terminates.
   */
  virtual void onEnd()
  {
    GroupProcess::onEnd();
    Behavior::onEnd();
  }
};

template <class DerivedBehavior>
class GroupBehaviorT : public virtual GroupBehavior, public BehaviorT<DerivedBehavior>
{
public:
  GroupBehaviorT(const Process* parent, unsigned int initialPriority, const PersistentUnitGroup* group)
    : GroupBehavior(parent, initialPriority, group)
    , BehaviorT(parent, initialPriority)
    , Behavior(parent, initialPriority)
    , FSM(parent)
    , Process(parent)
  {
  }
};
