#pragma once
#include "EngageEnemies.h"
#include "../../Behavior.h"
#include "../../../../PerceptualState/Requests/EnemyUnitsInArea.h"
#include "../../Actions/AttackMoveAction.h"
#include "../../Actions/AttackUnitAction.h"

class HealAllies;

// TODO: put back attack-move behavior

/**
* @brief The MedicsAndMarinesEngageEnemies behavior instructs a group of marines/medics to engage enemies.
*/
class MedicsAndMarinesEngageEnemies : public EngageEnemies
{
  // TODO: keep medics with the marines, move wounded marines away...
  //       terminate on EngageEnemies::Retreat when outnumbered

protected:
  //class EngagingEnemies;
  //friend class EngagingEnemies;

  /**
  * @brief The EngagingEnemies state is active when the group is engaging the enemies.
  *        New sub-behaviors are spawned upon entering this state.
  */
  class EngagingEnemies : public BehaviorState<EngagingEnemies>
  {
  public:
    EngagingEnemies(MedicsAndMarinesEngageEnemies& behavior);
    void prepare();
    virtual std::string getName() const { return "EngagingEnemies"; }
    void onSubBehaviorEnded(void* data);
    void OnUnitDestroyed(void* data);

  protected:
    void onEnterImpl();
    void onExitImpl();

    void FocusFire();

    friend class BehaviorState<EngagingEnemies>;
    typedef EnemyUnitsInAreaRequest<AreaTraits<PersistentUnitGroup>::Area> EnemyUnitsInAreaRequest;

    // Behavior
    MedicsAndMarinesEngageEnemies& m_behavior;

    // Variables
    PersistentUnitGroup m_marines;
    RECEPTACLE(EngagingEnemies, onSubBehaviorEnded) m_subBehaviorsReceptacle;
    RECEPTACLE(EngagingEnemies, OnUnitDestroyed) m_unitDestroyedReceptacle;

    // Actions
    AttackUnitAction m_attackUnitAction;

    // Transitions
    PeriodicRequestGenerator<1, EnemyUnitsInAreaRequest, UpdateArea<PersistentUnitGroup>> m_enemyUnitInAreaEvent;
    Transition<EngagingEnemies, Eval<NoEnemyUnitInArea, EnemyUnitsInAreaRequest>, NoTransitionAction, EngagingEnemies> m_transitionToSelf;

    typedef boost::tuple<
      PeriodicRequestGenerator<1, EnemyUnitsInAreaRequest, UpdateArea<PersistentUnitGroup>>&
      > events;
    events m_events;

    typedef boost::tuple<
      Transition<EngagingEnemies, Eval<NoEnemyUnitInArea, EnemyUnitsInAreaRequest>, NoTransitionAction, EngagingEnemies>&
    > transitions;
    transitions m_transitions;
  };

public:
  MedicsAndMarinesEngageEnemies(unsigned int initialPriority, PersistentUnitGroup* group)
    : EngageEnemies(initialPriority, group)
    , m_engagingEnemiesState(*this)
  {
  }

  virtual std::string getName() const
  {
    return "MedicsAndMarinesEngageEnemies (" + getObjectDescription(m_group) + ")";
  }

protected:
  virtual void enterInitialState()
  {
    m_engagingEnemiesState.prepare();
    m_engagingEnemiesState.onEnter();
  }

  // Arguments

  // Variables
  UnitGroup m_enemyUnits;

  // States
  EngagingEnemies m_engagingEnemiesState;
};
