#include "stdafx.h"
#include "AvoidEnemiesBehavior.h"
#include "../Layer1FSM.h"
#include "../Commands/MoveCommand.h"
#include "../../../../PerceptualState/PerceptualState.h"

///////////////////////////////////////////////////
// Idle state

AvoidEnemiesBehavior::Idle::Idle(AvoidEnemiesBehavior& behavior)
  : BehaviorStateT(behavior)
  //, m_stopCommand(*this)
  , m_timerEvent(*this, Scheduler::FSM_SCHEDULING_PRIORITY, 5, 5)
  , m_transitionToReadyState(
      *this,
      IsUnitIdle(behavior.m_unit), 
      NoTransitionAction(), 
      behavior.m_readyToAvoidState)
  , m_events(m_timerEvent)
  , m_transitions(m_transitionToReadyState)
{
}

void AvoidEnemiesBehavior::Idle::onEnter()
{
    Layer1FSM::getInstance().getArbitrator().
    submitCommand(m_context.m_unit, StopCommand(*this), Arbitration::ActionImportance(m_context));
}

///////////////////////////////////////////////////
// ReadyToAvoid state

AvoidEnemiesBehavior::ReadyToAvoid::ReadyToAvoid(AvoidEnemiesBehavior& behavior)
: BehaviorStateT(behavior)
  , m_timerEvent(*this, Scheduler::FSM_SCHEDULING_PRIORITY, 5, 5)
  , m_transitionToAvoidingState(
      *this,
      AtLeastOneUnit(), 
      NoTransitionAction(), 
      behavior.m_avoidingState)
  , m_events(m_timerEvent)
  , m_transitions(m_transitionToAvoidingState)
{
}

void AvoidEnemiesBehavior::ReadyToAvoid::onEnter()
{
}

///////////////////////////////////////////////////
// Avoiding state

AvoidEnemiesBehavior::Avoiding::Avoiding(AvoidEnemiesBehavior& behavior)
: BehaviorStateT(behavior)
  //, m_moveCommand(*this)
  , m_timerEvent(*this, Scheduler::FSM_SCHEDULING_PRIORITY, 5, 5)
  , m_transitionToSelf(
      *this,
      AtLeastOneUnit(),
      NoTransitionAction(), 
      *this)
  , m_transitionToIdle(
      *this,
      Not<AtLeastOneUnit>(AtLeastOneUnit()),
      NoTransitionAction(), 
      behavior.m_idleState)
  , m_events(m_timerEvent)
  , m_transitions(m_transitionToSelf, m_transitionToIdle)
{
}

void AvoidEnemiesBehavior::Avoiding::onEnter()
{  
  BWAPI::Position destination = Spar->getPerceptualState()->
    getSafeRetreatPosition(m_context.m_unit); //, m_context.m_enemyUnits);

  Layer1FSM::getInstance().getArbitrator().
    submitCommand(m_context.m_unit, MoveCommand(*this, destination), Arbitration::ActionImportance(m_context));
}

void AvoidEnemiesBehavior::Avoiding::onTimer()
{
  m_context.m_enemyUnits = Spar->getPerceptualState()->getEnemyUnits(Spar->getPerceptualState()->getUnitRecord(m_context.m_unit));
  m_transitionToIdle.testTransition(boost::tuple<const std::set<BWAPI::Unit*>&>(m_context.m_enemyUnits));
  m_transitionToSelf.testTransition(boost::tuple<const std::set<BWAPI::Unit*>&>(m_context.m_enemyUnits));
}

void AvoidEnemiesBehavior::ReadyToAvoid::onTimer()
{
  m_context.m_enemyUnits = Spar->getPerceptualState()->getEnemyUnits(UnitCircularLocation(Spar->getPerceptualState()->getUnitRecord(m_context.m_unit)));
  m_transitionToAvoidingState.testTransition(boost::tuple<const std::set<BWAPI::Unit*>&>(m_context.m_enemyUnits));
}