#include "stdafx.h"
#include "../Layer2Managers.h"
#include "L2Research.h"

L2Research::UnitRecordGroup L2Research::_getUnitsInvolved() const
{
  UnitRecordGroup unitsInvolved = Research::_getUnitsInvolved();
  if (m_building != NULL)
    unitsInvolved.insert(m_building);
  return unitsInvolved;
}

void L2Research::onStartImplementation()
{
  L2TacticalAction::onStartImplementation();
}

void L2Research::onCancelImplementation()
{
  L2TacticalAction::onCancelImplementation();

  if(m_researchProcess != NULL)
  {
    m_researchProcess->getTerminateEvent().unsubscribe(m_researchTerminateSubscriberID);
    m_researchProcess->cancel();
  }
  terminate(Cancelled);
}

void L2Research::onEndImplementation()
{
  L2TacticalAction::onEndImplementation();
  Layer2Managers::getInstance().terminateResourcesRequest(m_resourcesRequest);
  if (m_researchProcess != NULL)
    m_researchProcess->getTerminateEvent().unsubscribe(m_researchTerminateSubscriberID);
  if(m_building != NULL)
    dynamic_cast<Layer2ManagersUnitData&>(BWAPI::getUnitData(m_building)).setInUseFlag(false);
  m_building = NULL;
}

void L2Research::onResearchProcessTerminate(void*)
{
  m_researchProcess->getTerminateEvent().unsubscribe(m_researchTerminateSubscriberID);
  MonitoringProcess* research = m_researchProcess;
  m_researchProcess = NULL;
  terminate(research->getTerminationMode());
}

void L2UpgradeResearch::onStartImplementation()
{
  L2Research::onStartImplementation(); 
  Layer2Managers::getInstance().requestResources(
    m_priority, 
    ActionResources(Resources(m_upgrade->getUpgrade(),m_upgrade->getLevel()),Spar->getPerceptualState()->getMap(), m_upgrade->getUpgrade().whatUpgrades()), 
    m_resourcesRequest);
}

void L2UpgradeResearch::onResourcesAllocated(void*, BWAPI::Unit* building)
{
  assert(building != NULL && building->getType() == m_upgrade->getUpgrade().whatUpgrades());

  if(building->getRemainingResearchTime() == 0 &&
     building->getRemainingUpgradeTime() == 0 &&
     building->getRemainingTrainTime() == 0)
  {
    m_building = building;
    assert(dynamic_cast<Layer2ManagersUnitData&>(BWAPI::getUnitData(m_building)).isInUse());

    Resources oldResources = Resources(BWAPI::Broodwar->self());
    m_building->upgrade(m_upgrade->getUpgrade());
    assert(oldResources == Resources(BWAPI::Broodwar->self()) + Resources(m_upgrade->getUpgrade(),m_upgrade->getLevel()));

    Layer2Managers::getInstance().terminateResourcesRequest(m_resourcesRequest);

    //TELL Perceptual that an upgrade as been started
    m_researchProcess = Spar->getPerceptualState()->onUpgradeStarted(m_upgrade,m_building);
    assert(!m_researchProcess->isTerminated());
    if (m_researchProcess->isTerminated())
      onResearchProcessTerminate(NULL);
    else
      m_researchTerminateSubscriberID = m_researchProcess->getTerminateEvent().subscribe(&m_researchTerminateEventHandler, NULL);
  }
  else
  {
    //SHUT
    //DOWN
    //EVERYTHING!
    cancel();
  }
}

void L2TechResearch::onStartImplementation()
{
  L2Research::onStartImplementation(); 
  Layer2Managers::getInstance().requestResources(
    m_priority, 
    ActionResources(Resources(m_tech->getTech()),Spar->getPerceptualState()->getMap(), m_tech->getTech().whatResearches()), 
    m_resourcesRequest);
}

void L2TechResearch::onResourcesAllocated(void*, BWAPI::Unit* building)
{
  assert(building != NULL && building->getType() == m_tech->getTech().whatResearches());

  if(building->getRemainingResearchTime() == 0 &&
     building->getRemainingUpgradeTime() == 0 &&
     building->getRemainingTrainTime() == 0)
  {
    m_building = building;
    assert(dynamic_cast<Layer2ManagersUnitData&>(BWAPI::getUnitData(m_building)).isInUse());

    Resources oldResources = Resources(BWAPI::Broodwar->self());
    m_building->research(m_tech->getTech());
    assert(oldResources == Resources(BWAPI::Broodwar->self()) + Resources(m_tech->getTech()));
  
    Layer2Managers::getInstance().terminateResourcesRequest(m_resourcesRequest);

    //TELL Perceptual that a tech as been started
    m_researchProcess = Spar->getPerceptualState()->onResearchStarted(m_tech,m_building);
    assert(!m_researchProcess->isTerminated());
    if (m_researchProcess->isTerminated())
      onResearchProcessTerminate(NULL);
    else
      m_researchTerminateSubscriberID = m_researchProcess->getTerminateEvent().subscribe(&m_researchTerminateEventHandler, NULL);
  }
  else
  {
    //SHUT
    //DOWN
    //EVERYTHING!
    cancel();
  }
}
