#include "stdafx.h"
#include "L3BaseLocation.h"
#include "Layer3Script.h"

void L3BaseLocation::buildAssimilator(const Process* parent)
{
  if (getNbNeutralUnits(BWAPI::UnitTypes::Resource_Vespene_Geyser) > getNbOwnUnits(BWAPI::UnitTypes::Protoss_Assimilator) + getLastKnownNbEnemyRefineries() + m_buildAssimilators.size())
  {
    Build *buildAssimilator = Layer3Script::getInstance().getLayer2().instantiateBuild(
      parent,
      PRIORITY_BUILD_ASSIMILATOR, 
      this, 
      BWAPI::UnitTypes::Protoss_Assimilator);
    m_buildAssimilators.add(buildAssimilator);
    buildAssimilator->start();
  }
}

void L3BaseLocation::instantiateCollectActions(const Process* parent)
{
  assert(m_collectMinerals == NULL);
  assert(m_collectGas == NULL);

  m_collectMinerals = Layer3Script::getInstance().getLayer2().instantiateCollectMinerals(
    parent,
    PRIORITY_COLLECT_MINERALS, 
    &PersistentUnitGroup::EmptyGroup, 
    this);
  m_collectMinerals->getTerminateEvent().subscribe(&m_collectMineralsEndedEventHandler, m_collectMinerals);

  m_collectGas = Layer3Script::getInstance().getLayer2().instantiateCollectGas(
    parent,
    PRIORITY_COLLECT_GAS,
    &PersistentUnitGroup::EmptyGroup,
    this);
  m_collectGas->getTerminateEvent().subscribe(&m_collectGasEndedEventHandler, m_collectGas);
}

void L3BaseLocation::executeCollectResources(const Process* parent)
{
  unused(parent);
  assert(m_collectMinerals->getParent() == parent);
  assert(m_collectGas->getParent() == parent);

  if (m_collectMinerals->isWaitingToExecute() && getLastKnownNbCrystalsLeft() > 0)
  {
    m_collectMinerals->start();
  }
  if (m_collectGas->isWaitingToExecute() && getNbCompletedOwnUnits(BWAPI::UnitTypes::Protoss_Assimilator) > 0)
  {
    m_collectGas->start();
  }
}

void L3BaseLocation::onCollectMineralsEnded(void* data)
{
  m_collectMinerals = Layer3Script::getInstance().getLayer2().instantiateCollectMinerals(
    reinterpret_cast<const CollectMinerals*>(data)->getParent(),
    PRIORITY_COLLECT_MINERALS, 
    reinterpret_cast<const CollectMinerals*>(data)->getGroup(), 
    this);
  m_collectMinerals->getTerminateEvent().subscribe(&m_collectMineralsEndedEventHandler, m_collectMinerals);
}

void L3BaseLocation::onCollectGasEnded(void* data)
{
  m_collectGas = Layer3Script::getInstance().getLayer2().instantiateCollectGas(
    reinterpret_cast<const CollectGas*>(data)->getParent(),
    PRIORITY_COLLECT_GAS, 
    reinterpret_cast<const CollectGas*>(data)->getGroup(), 
    this);
  m_collectGas->getTerminateEvent().subscribe(&m_collectGasEndedEventHandler, m_collectGas);
}

void L3BaseLocation::executeRecruitProbes(const Process* parent)
{
  if (m_recruitProbes == NULL)
  {
    m_recruitProbes = Layer3Script::getInstance().getLayer2().instantiateRecruit(
      parent,
      PRIORITY_RECRUIT_PROBES, 
      this, 
      BWAPI::UnitTypes::Protoss_Probe, 
      true);
    m_recruitProbes->getUnitRecruitedEvent().subscribe(&m_probeRecruitedEventHandler, NULL);
    m_recruitProbes->start();
  }
  else
  {
    assert(m_recruitProbes->isExecuting());
  }
}

void L3BaseLocation::onProbeRecruited(void*, const Recruit*, BWAPI::Unit* probe)
{
  assert(probe->getType() == BWAPI::UnitTypes::Protoss_Probe);

  m_collectMinerals->addUnit(probe);
}

void L3BaseLocation::cancelRecruitProbes()
{
  if (m_recruitProbes != NULL)
  {
    assert(m_recruitProbes->isExecuting());

    m_recruitProbes->cancel();
  }
}
