#pragma once
#include "../../../../../../PerceptualState/Locations/Dynamic/GroupRectangularLocation.h"
#include "../../../Behaviors/General/EngageEnemies/EngageEnemiesBehavior.h"
#include "../../../Conditions/AtLeastOneUnit.h"
#include "UnitCarefulAttackBehavior.h"
#include <functional>

// This behavior will cause units to run after a fleeing unit (and get hit in the process)

class GroupCarefulAttackBehavior : public EngageEnemiesBehaviorT<GroupCarefulAttackBehavior>
{
protected:
  //class Engaging;
  //friend class Engaging;

  /**
  * @brief The Engaging state is active when the group is engaging the enemies.
  *        New sub-behaviors are spawned upon entering this state.
  */
  class Engaging : public BehaviorStateT<GroupCarefulAttackBehavior, Engaging>
  {
  public:
    Engaging(GroupCarefulAttackBehavior& behavior);
    void onEnter();
    void onExit() {}

    typedef boost::tuple<
      //EnemyUnitsInLocationRequest&
    > Events;
		const Events m_events;

    typedef boost::tuple<
    > Transitions;
		const Transitions m_transitions;

  protected:
    void onEnemyUnitDestroyed(void* data);

    void findTarget();
    void setTarget();
    class SetTarget : public std::unary_function<Process*,SafeListBase::IterationStep>
    {
    public:
      SetTarget(BWAPI::Unit* target)
        : m_target(target)
      {}
      SafeListBase::IterationStep operator()(Process* subBehavior) const
      {
        dynamic_cast<UnitCarefulAttackBehavior*>(subBehavior)->setTarget(m_target);
        return SafeListBase::IterationStep();
      }
    protected:
      BWAPI::Unit* const m_target;

      SetTarget & operator=(const SetTarget &);
    };

    // Variables
    EVENT_HANDLER(Engaging, onEnemyUnitDestroyed) m_enemyUnitDestroyedEventHandler;

    // Actions

    // Transitions
  };

public:
  GroupCarefulAttackBehavior(const Process* parent, unsigned int initialPriority, const PersistentUnitGroup* group)
    : EngageEnemiesBehaviorT(parent, initialPriority, group)
    , EngageEnemiesBehavior(parent, initialPriority, group)
    , GroupBehavior(parent, initialPriority, group)
    , Behavior(parent, initialPriority)
    , FSM(parent)
    , Process(parent)
    , m_engagingState(*this)
    , m_target(NULL)
    , m_states(m_engagingState)
  {
  }

  typedef boost::tuple<
      Engaging&
    > States;
	const States m_states;

protected:
  virtual void onStart()
  {
    EngageEnemiesBehaviorT::onStart();
    m_engagingState.enter();
  }

  virtual void onUnitAddedToGroup(void* data, BWAPI::Unit* unit)
  {
    unused(data);
    unused(unit);
  }

  virtual void onUnitRemovedFromGroup(void* data, BWAPI::Unit* unit)
  {
    unused(data);
    unused(unit);
  }

  // Arguments

  // Variables
  std::set<BWAPI::Unit*> m_enemyUnits;
  BWAPI::Unit *m_target;

  // States
  Engaging m_engagingState;
};
