#pragma once
#include "UnitAttackBehavior.h"

class DefaultUnitAttackBehavior : public UnitAttackBehaviorT<DefaultUnitAttackBehavior>
{
  class Engaging;
  class Idling;

public:
  DefaultUnitAttackBehavior(const Process* parent, unsigned int initialPriority, BWAPI::Unit* unit);

  bool selectTarget(const std::set<BWAPI::Unit*>& enemies);

protected:
  virtual void _output(std::ostream& out) const
  {
    out << "DefaultUnitAttackBehavior(" << *m_unit << ")";
  }

  virtual void onStart()
  {
    UnitBehaviorT::onStart();
    m_idlingState.enter();
  }

private:
  BWAPI::Unit* m_target;

  // Engaging state ////////////////////////////////////////////////////////////
  class Engaging : public BehaviorStateT<DefaultUnitAttackBehavior, Engaging>
  {
  public:
    Engaging(DefaultUnitAttackBehavior& behavior);
    void onEnter();
    void onExit();

    //void onTimer();

    void targetChanged(BWAPI::Unit* oldTarget);
  private:
    void onTargetEvaded(void*);

    //AttackUnitCommand m_attackAction;

    typedef Transition<Engaging, NoCondition, NoTransitionAction, Idling> IdlingTransition;
    IdlingTransition m_idlingTransition;

    //typedef SCHEDULER_EVENT_HANDLER(Engaging, onTimer) TimerEvent;
    //TimerEvent m_timerEvent;

    BWAPI::OnIndividualUnitEvade::SubscriberID m_targetEvadedId;    
    EVENT_HANDLER(Engaging, onTargetEvaded) m_targetEvadedEventHandler;

  public:
    typedef boost::tuple<> Events;
    const Events m_events;

    typedef boost::tuple<
      IdlingTransition&
    > Transitions;
    const Transitions m_transitions;
  };

  
  // Idling state //////////////////////////////////////////////////////////////
  class Idling : public BehaviorStateT<DefaultUnitAttackBehavior, Idling>
  {
  public:
    Idling(DefaultUnitAttackBehavior& behavior);
    void onEnter() {}
    void onExit() {}

    void onTargetChanged();

  private:
    typedef Transition<Idling, NoCondition, NoTransitionAction, Engaging> EngagingTransition;
    EngagingTransition m_engagingTransition;
    
  public:
    typedef boost::tuple<> Events;
    const Events m_events;

    typedef boost::tuple<
      EngagingTransition&
    > Transitions;
    const Transitions m_transitions;
  };

  // Variables

  // States
  Engaging m_engagingState;
  Idling m_idlingState;

public:
  typedef boost::tuple<
    Engaging&,
    Idling&
  > States;
  const States m_states;
};