#include "HealAllies.h"
#include "../Conditions/AlliesHealed.h"
#include "../../../PersistentUnitGroup.h"
#include "../Arbitrator.h"

const HealAllies::TerminationMode HealAllies::AlliesDead;

//------------------------------------------------------------------------------
// Idle state
//------------------------------------------------------------------------------
HealAllies::Idle::Idle(HealAllies& behavior)
  : BehaviorState()
  , m_behavior(behavior)
  , m_moveAction(*this)
  , m_transitionToHealingState(
      *this,
      m_alliesWoundedEvent,
      AlliesWounded<PersistentUnitGroup>(behavior.m_allies),
      NoTransitionAction(),
      behavior.m_healingState)
  , m_transitionToSelf(
      *this,
      m_alliesWoundedEvent, // Same event, the other transition should have priority...
      NoCondition(),
      NoTransitionAction(),
      *this)
  , m_events(m_alliesWoundedEvent)
  , m_transitions(m_transitionToHealingState, m_transitionToSelf)
{
}

void HealAllies::Idle::prepare()
{
}

void HealAllies::Idle::onEnterImpl()
{
  // TODO Go between allies and enemies instead

  BWAPI::Position destination = m_behavior.m_allies->getCenter();
  m_moveAction.setDestination(destination);
  Arbitration::getArbitrator().
    submitAction(m_behavior.m_unit, m_moveAction, Arbitration::ActionImportance(*this));
}

//------------------------------------------------------------------------------
// Healing state
//------------------------------------------------------------------------------
HealAllies::Healing::Healing(HealAllies& behavior)
  : BehaviorState()
  , m_behavior(behavior)
  , m_healAction(*this)
  , m_transitionToIdleState(
      *this,
      m_alliesHealedEvent,
      AlliesHealed<PersistentUnitGroup>(behavior.m_allies),
      NoTransitionAction(),
      behavior.m_idleState)
  , m_events(m_alliesHealedEvent)
  , m_transitions(m_transitionToIdleState)
  //, m_transitionToSelf(*this,
  //                     this->m_alliesHealedEvent,
  //                     AlliesWounded<PersistentUnitGroup>(behavior.m_allies),
  //                     NoTransitionAction(),
  //                     *this)
{
}

void HealAllies::Healing::onEnterImpl()
{
  // Select the unit that has the lowest relative HP, prioritizing those which are unattended to
  PersistentUnitGroup::const_iterator i = m_behavior.m_allies->begin();
  BWAPI::Unit* unitToHeal = *(i++);
  for(; i != m_behavior.m_allies->end(); ++i)
  {
    BWAPI::Unit* unit = *i;
    if(unit->isBeingHealed() == unitToHeal->isBeingHealed())
    {
      float hp1 = static_cast<float>(unitToHeal->getHitPoints()) / unitToHeal->getType().maxHitPoints();
      float hp2 = static_cast<float>(unit->getHitPoints()) / unit->getType().maxHitPoints();

      unitToHeal = hp1 < hp2 ? unitToHeal : unit;
    }
    else if(!unit->isBeingHealed())
    {
      unitToHeal = unit;
    }
  }

  m_healAction.setUnitToHeal(unitToHeal);
  Arbitration::getArbitrator().
    submitAction(m_behavior.m_unit, m_healAction, Arbitration::ActionImportance(*this));
}
