#pragma once
#include "../../../../../PerceptualState/Locations/Dynamic/GroupRectangularLocation.h"
#include "../../Behaviors/General/EngageEnemies/EngageEnemiesBehavior.h"
#include "../../Conditions/AtLeastOneUnit.h"
#include "../DodgeBehavior.h"
#include "../../Commands/AttackUnitCommand.h"

// This behavior is probably full of bugs; it should be adapted to our framework before being used

class FocusFireBehavior : public EngageEnemiesBehaviorT<FocusFireBehavior>
{
protected:
  class Engaging;
  friend class Engaging;

  class Engaging : public BehaviorStateT<FocusFireBehavior, Engaging>
  {
  public:
    Engaging(FocusFireBehavior& behavior);
    ~Engaging();
    void onEnter();
    void onExit();

    typedef SCHEDULER_EVENT_HANDLER(Engaging, onTimer) TimerEvent;

    typedef boost::tuple<
      TimerEvent&
    > Events;
		const Events m_events;

    typedef boost::tuple<
      //Transition<Engaging, NoCondition, NoTransitionAction, Engaging>&
    > Transitions;
		const Transitions m_transitions;

  protected:
    void onUnitDestroyed(void* data);
    void onTimer();

    void findTargetAndFire();
    static BWAPI::Unit* getWeakest(const std::set<BWAPI::Unit*> &group);

    // Variables

    // Callback functors
    EVENT_HANDLER(Engaging, onUnitDestroyed) m_unitDestroyedEventHandler;

    // Actions
    //AttackUnitCommand m_attackAction;

    // Transitions
    TimerEvent m_timerEvent;
    //Transition<Engaging, NoCondition, NoTransitionAction, Engaging> m_transitionToSelf;
  };

public:
  FocusFireBehavior(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_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;

  // States
  Engaging m_engagingState;
};
