#include "stdafx.h"
#include "EnemyArmyComposition.h"
#include "../PerceptualState.h"

EnemyArmyComposition::EnemyArmyComposition()
  : m_unitRecordCreateEventHandler(*this)
  , m_unitRecordRenegadeEventHandler(*this)
  , m_enemyUnitRecordDestroyEventHandler(*this)
  , m_enemyUnitRecordMorphEventHandler(*this)
  , m_enemyUnitRecordRenegadeEventHandler(*this)
{
  m_unitRecordCreateID = Spar->getPerceptualState()->getUnitRecordCreateEvent().subscribe(&m_unitRecordCreateEventHandler, NULL);
  m_unitRecordRenegadeID = Spar->getPerceptualState()->getUnitRecordRenegadeEvent().subscribe(&m_unitRecordRenegadeEventHandler, NULL);
}

EnemyArmyComposition::~EnemyArmyComposition()
{
  Spar->getPerceptualState()->getUnitRecordCreateEvent().unsubscribe(m_unitRecordCreateID);
  Spar->getPerceptualState()->getUnitRecordRenegadeEvent().unsubscribe(m_unitRecordRenegadeID);

  stdext::hash_multimap<BWAPI::UnitType, UnitWrapper>::iterator it = m_enemyUnits.begin();
  while (it != m_enemyUnits.end())
  {
    stdext::hash_multimap<BWAPI::UnitType, UnitWrapper>::iterator next = 
      ++(stdext::hash_multimap<BWAPI::UnitType, UnitWrapper>::iterator(it));
    removeUnitInternal(&it->second);
    it = next;
  }
}

void EnemyArmyComposition::onUnitRecordCreate(void*, UnitRecord* unitRecord)
{
  if (unitRecord->getPlayer() == BWAPI::Broodwar->enemy())
  {
    addUnitInternal(unitRecord);
  }
}

void EnemyArmyComposition::onUnitRecordRenegade(void*, UnitRecord* unitRecord, BWAPI::Player*)
{
  if (unitRecord->getPlayer() == BWAPI::Broodwar->enemy())
  {
    addUnitInternal(unitRecord);
  }
}

void EnemyArmyComposition::onEnemyUnitRecordDestroy(void* data)
{
  UnitWrapper* unitWrapper = reinterpret_cast<UnitWrapper*>(data);
  removeUnitInternal(unitWrapper);
}

void EnemyArmyComposition::onEnemyUnitRecordMorph(void* data, BWAPI::UnitType)
{
  UnitWrapper* unitWrapper = reinterpret_cast<UnitWrapper*>(data);
  UnitRecord* unitRecord = unitWrapper->m_enemyUnitRecord;
  if (unitWrapper->m_posInContainer->first != unitRecord->getType())
  {
    unitRecord->acquire(this);
    removeUnitInternal(unitWrapper);
    addUnitInternal(unitRecord);
    unitRecord->release(this);
  }
}

void EnemyArmyComposition::onEnemyUnitRecordRenegade(void* data, BWAPI::Player*)
{
  UnitWrapper* unitWrapper = reinterpret_cast<UnitWrapper*>(data);
  UnitRecord* unitRecord = unitWrapper->m_enemyUnitRecord;
  if (unitRecord->getPlayer() != BWAPI::Broodwar->enemy())
  {
    removeUnitInternal(unitWrapper);
  }
}