#pragma once
#include "../../../Behaviors/UnitBehavior.h"
#include "../../../Conditions/IsIdle.h"
#include "../../../Conditions/UnitLoaded.h"
#include "../../../Conditions/AtLeastOneUnit.h"
#include "../../../Commands/ReaverCommands/BuildScarabCommand.h"
#include "../../../Commands/ReaverCommands/ReaverAttackCommand.h"
#include "../../../../../../Scheduler/SchedulerTaskHelper.h"

class ReaverControlBehavior : public UnitBehaviorT<ReaverControlBehavior>
{
protected:
	class IsLoaded;
	class Build;
	class Attack;
	friend class IsLoaded;
	friend class Build;
	friend class Attack;

	class IsLoaded : public BehaviorStateT<ReaverControlBehavior, IsLoaded>
	{
	public:
		IsLoaded(ReaverControlBehavior& behavior);
		void onEnter();
		void onExit() {}

    void onTimer()
    {
      m_transitionToBuildState.testTransition(boost::make_tuple());
    }

    typedef SCHEDULER_EVENT_HANDLER(IsLoaded, onTimer) TimerEvent;

		typedef boost::tuple<
			TimerEvent&
			> Events;
		const Events m_events;
    
		typedef boost::tuple<
			Transition<IsLoaded, UnitOnGround, NoTransitionAction, Build>&
			> Transitions;
		const Transitions m_transitions;

	protected:
		// Variables

		// Actions

	    // Transitions
		TimerEvent m_unitIsUnloaded;
		Transition<IsLoaded, UnitOnGround, NoTransitionAction, Build> m_transitionToBuildState;
	};

	class Build : public BehaviorStateT<ReaverControlBehavior, Build>
	{
	public:
		Build(ReaverControlBehavior& behavior);
		void onEnter();
		void onExit() {}

    void onTimer()
    {
      m_transitionToAttackState.testTransition(boost::make_tuple());
      m_transitionToLoadedState.testTransition(boost::make_tuple());
    }

    typedef SCHEDULER_EVENT_HANDLER(Build, onTimer) TimerEvent;

		typedef boost::tuple<
			TimerEvent&
			> Events;
		const Events m_events;
    
		typedef boost::tuple<
			Transition<Build, UnitOnGround, NoTransitionAction, Attack>&,
			Transition<Build, UnitLoaded, NoTransitionAction, IsLoaded>&
			> Transitions;
		const Transitions m_transitions;

	protected:
		// Variables

		// Actions
		//BuildScarabCommand m_buildScarab;

	    // Transitions
    TimerEvent m_unitIsUnloaded;
		Transition<Build, UnitOnGround, NoTransitionAction, Attack> m_transitionToAttackState;
		Transition<Build, UnitLoaded, NoTransitionAction, IsLoaded> m_transitionToLoadedState;
	};

	class Attack : public BehaviorStateT<ReaverControlBehavior, Attack>
	{
	public:
		Attack(ReaverControlBehavior& behavior);
		void onEnter();
		void onExit() {}		

    void onTimer()
    {
      m_transitionToBuildState.testTransition(boost::make_tuple());
      m_transitionToLoadedState.testTransition(boost::make_tuple());
    }

    typedef SCHEDULER_EVENT_HANDLER(Attack, onTimer) TimerEvent;

		typedef boost::tuple<
			TimerEvent&
			> Events;
		const Events m_events;
    
		typedef boost::tuple<
			Transition<Attack, UnitOnGround, NoTransitionAction, Build>&,
			Transition<Attack, UnitLoaded, NoTransitionAction, IsLoaded>&
			> Transitions;
		const Transitions m_transitions;

	protected:
		// Variables

		// Actions
		//ReaverAttackCommand m_reaverAttack;

	    // Transitions
		TimerEvent m_unitIsUnloaded;
		Transition<Attack, UnitOnGround, NoTransitionAction, Build> m_transitionToBuildState;
		Transition<Attack, UnitLoaded, NoTransitionAction, IsLoaded> m_transitionToLoadedState;
	};

public:
	ReaverControlBehavior(const Process* parent, unsigned int initialPriority, BWAPI::Unit* reaver)
		: UnitBehaviorT(parent, initialPriority, reaver)
    , UnitBehavior(parent, initialPriority, reaver)
    , Behavior(parent, initialPriority)
    , FSM(parent)
    , Process(parent)
		, m_isLoadedState(*this), m_buildState(*this),m_attackState(*this)
    , m_states(m_isLoadedState, m_buildState, m_attackState)
	{
	}

  typedef boost::tuple<
      IsLoaded&,
      Build&,
      Attack&
    > States;
	const States m_states;

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

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

  // Arguments

  // Variables

  // States
  IsLoaded m_isLoadedState;
  Build m_buildState;
  Attack m_attackState;
};