#pragma once
#include "UnitMoveBehavior.h"

/**
 * @brief The NativeUnitMoveBehavior uses StarCraft built-in pathfinding algorithms to help a
 *        unit move to a destination.
 */
class NativeUnitMoveBehavior : public UnitMoveBehaviorT<NativeUnitMoveBehavior>
{
protected:
  class Goto;
  friend class Goto;
  friend class UnitMoveBehaviorT<NativeUnitMoveBehavior>;

  class Goto : public UnitMoveBehaviorT::Goto
  {
  public:
    Goto(NativeUnitMoveBehavior& behavior, size_t refreshDelay);
    void onEnter();
    void onExit();
    void onTimer();

    typedef boost::tuple<
      TimerEvent&
#ifdef NON_FINAL_VERSION
      ,FrameDebugEvent&
#endif
    > Events;
    const Events m_events;

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

public:
  NativeUnitMoveBehavior(const Process* parent, unsigned int initialPriority, BWAPI::Unit* unit,
                         BWAPI::Position destination, const MoveOptions& moveOptions)
    : UnitMoveBehaviorT(parent, initialPriority, unit, destination, moveOptions)
    , UnitMoveBehavior(parent, initialPriority, unit, destination, moveOptions)
    , UnitBehavior(parent, initialPriority, unit)
    , Behavior(parent, initialPriority)
    , FSM(parent)
    , Process(parent)
    , m_gotoState(*this, moveOptions.m_refreshRate)
    , m_states(m_gotoState)
  {
  }

  static MoveOptions getDefaultMoveOptions(
    size_t maxDistance = DEFAULT_UNIT_MAX_DISTANCE, 
    size_t refreshRate = 10, 
    size_t givingUpDelay = boost::numeric::bounds<size_t>::highest(), 
    bool attackMove = false)
  {
    return MoveOptions(DefaultEvaluator, DefaultIsObstacle, 0, maxDistance, refreshRate, givingUpDelay, 0.0, false, attackMove);
  }

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

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

  // States
  Goto m_gotoState;
};
