#include "stdafx.h"
#include "ReaverControlBehavior.h"
#include "../../../Layer1FSM.h"
#include "../../../../../../PerceptualState/Locations/Static/Shape/CircularLocation.h"
#include "../../../../../../PerceptualState/PerceptualState.h"

///////////////////////////////////////////////////
// IsLoaded state

ReaverControlBehavior::IsLoaded::IsLoaded(ReaverControlBehavior& behavior)
: BehaviorStateT(behavior)
, m_unitIsUnloaded(*this, Scheduler::FSM_SCHEDULING_PRIORITY, 5, 5)
, m_transitionToBuildState(
                           *this,
                           UnitOnGround(behavior.m_unit), 
                           NoTransitionAction(), 
                           behavior.m_buildState)
, m_events(m_unitIsUnloaded)
, m_transitions(m_transitionToBuildState)
{
}

void ReaverControlBehavior::IsLoaded::onEnter()
{
}

///////////////////////////////////////////////////
// Build state

ReaverControlBehavior::Build::Build(ReaverControlBehavior& behavior)
: BehaviorStateT(behavior)
//, m_buildScarab(*this)
, m_unitIsUnloaded(*this, Scheduler::FSM_SCHEDULING_PRIORITY, 15, 15)
, m_transitionToAttackState(
                            *this,
                            UnitOnGround(behavior.m_unit),
                            NoTransitionAction(), 
                            behavior.m_attackState)
, m_transitionToLoadedState(
                            *this,
                            UnitLoaded(behavior.m_unit),
                            NoTransitionAction(), 
                            behavior.m_isLoadedState)
, m_events(m_unitIsUnloaded)
, m_transitions(m_transitionToAttackState, m_transitionToLoadedState)
{
}

void ReaverControlBehavior::Build::onEnter()
{  
  Layer1FSM::getInstance().getArbitrator().submitCommand(m_context.m_unit, BuildScarabCommand(*this), Arbitration::ActionImportance(m_context));
}

///////////////////////////////////////////////////
// Attack state

ReaverControlBehavior::Attack::Attack(ReaverControlBehavior& behavior)
: BehaviorStateT(behavior)
//, m_reaverAttack(*this)
, m_unitIsUnloaded(*this, Scheduler::FSM_SCHEDULING_PRIORITY, 15, 15)
, m_transitionToBuildState(
                           *this,
                           UnitOnGround(behavior.m_unit),
                           NoTransitionAction(), 
                           behavior.m_buildState)
, m_transitionToLoadedState(
                           *this,
                           UnitLoaded(behavior.m_unit),
                           NoTransitionAction(), 
                           behavior.m_isLoadedState)
, m_events(m_unitIsUnloaded)
, m_transitions(m_transitionToBuildState, m_transitionToLoadedState)
{
}

BWAPI::Unit* getReaverTarget(BWAPI::Unit* reaver)
{  
  BWAPI::Unit* target = 0;
  BWAPI::Unit* secondChoice = 0;
  double distance = boost::numeric::bounds<double>::highest();
  BWAPI::Position position = reaver->getPosition();
  CircularLocation location = CircularLocation(position,256+32);
  std::set<BWAPI::Unit*> enemyGroup = Spar->getPerceptualState()->getEnemyUnits(location);
  bool noTarget = true;
  for (std::set<BWAPI::Unit*>::const_iterator it = enemyGroup.begin(); it != enemyGroup.end(); ++it)
  {
    if((*it)->getType().canAttack() && !(*it)->getType().isFlyer() && !(*it)->getType().isFlyingBuilding()){
      int dist = (*it)->getDistance(reaver);
      if(dist<distance){
        distance = dist;
        target = *it;
      }
      noTarget=false;
    }else if(noTarget && !(*it)->getType().isFlyer()){
      secondChoice = *it;
      noTarget=false;
    }
  }
  if(noTarget){
    return NULL;
  }
  if(distance == boost::numeric::bounds<double>::highest()){
    return secondChoice;
  }
  return target;

}

void ReaverControlBehavior::Attack::onEnter()
{  
  BWAPI::Unit* target = getReaverTarget(m_context.m_unit);
  if(target != NULL){
    Layer1FSM::getInstance().getArbitrator().
      submitCommand(m_context.m_unit, ReaverAttackCommand(*this, target), Arbitration::ActionImportance(m_context));
  }
}