#include "stdafx.h"
#include "RecruitArmyProcess.h"
#include "../../../../PerceptualState/PerceptualState.h"
#include "../Layer3Script.h"

void RecruitArmyProcess::run()
{
  const ArmyComposition& targetArmyComposition = Layer3Script::getInstance().getTargetArmyComposition();

  //
  // Infinite recruit
  //
  bool executeInfiniteRecruit = false;
  if (m_infiniteRecruit == NULL)
  {
    executeInfiniteRecruit = true;
  }
  else if (m_infiniteRecruit->getUnitsToRecruit() != targetArmyComposition.getUnlimitedComposition())
  {
    // Could be m_infiniteRecruit->updateArmyComposition(...)
    m_infiniteRecruit->cancel();
    executeInfiniteRecruit = true;
  }
  if (executeInfiniteRecruit)
  {
    m_infiniteRecruit = Layer3Script::getInstance().getLayer2().instantiateRecruit(
      this,
      PRIORITY_RECRUIT_ARMY, 
      Spar->getPerceptualState()->getMap(), 
      targetArmyComposition.getUnlimitedComposition(), 
      true);
    m_infiniteRecruit->start();
  }

  //
  // Finite recruits
  //
  const std::map<BWAPI::UnitType, size_t>& limitedComposition = targetArmyComposition.getLimitedComposition();
  for (std::map<BWAPI::UnitType, size_t>::const_iterator it = limitedComposition.begin(); it != limitedComposition.end(); ++it)
  {
    // TODO: cancel individual recruits if too many?
    std::pair<std::map<BWAPI::UnitType, ProcessContainerList<Recruit>>::iterator, bool> result = 
      m_finiteRecruits.insert(std::make_pair(it->first, ProcessContainerList<Recruit>(*this)));
    ProcessContainerList<Recruit>& list = result.first->second;
    for (size_t i = list.size(); i < it->second; ++i)
    {
      const unsigned int priority = it->first == BWAPI::UnitTypes::Protoss_Observer ? PRIORITY_RECRUIT_OBSERVER : PRIORITY_RECRUIT_ARMY;
      std::map<BWAPI::UnitType, size_t> oneUnit;
      oneUnit.insert(std::make_pair(it->first, 1));
      Recruit* recruit = Layer3Script::getInstance().getLayer2().instantiateRecruit(
        this,
        priority, 
        Spar->getPerceptualState()->getMap(), 
        oneUnit, 
        false);
      list.add(recruit);
      recruit->start();
    }
  }
}

