#include "stdafx.h"
#include "PersistentUnitGroup.h"
#include "../SparAIContainer.h"
#include "../PerceptualState/PerceptualState.h"

PersistentUnitGroup::~PersistentUnitGroup()
{
  m_groupDestroyedEvent.raise();

  UnitWrapperSet::iterator it = m_group.begin();
  while (it != m_group.end())
  {
    UnitWrapperSet::iterator next = it;
    ++next;
    remove(it);
    it = next;
  }
}

void PersistentUnitGroup::_output(std::ostream& out) const
{
  //GroupBase::_output(out);
  out << "Persistent unit group \"" << m_name << "\"";
}

bool PersistentUnitGroup::insert(BWAPI::Unit* unit)
{
#ifdef USE_SPAR_LOG
    if (!(unit->exists() && !BWAPI::isDestroyed(unit)))
    {
      SPAR_LOG(LogTypes.GENERAL_ERROR, "Error adding a destroyed or non-existing unit to a group: \"%s\"",
        toString(unit).c_str());
    }
#endif
  assert(unit->exists() && !BWAPI::isDestroyed(unit));

  std::pair<UnitWrapperSet::iterator, bool> p = m_group.insert(UnitWrapper(unit));
  if (p.second)
  {
    p.first->m_unitPosInSet = p.first;
    PerceptualStateUnitData::OnIndividualUnitDestroy::SubscriberID unitManagerID = 
      BWAPI::getIndividualUnitDestroyEvent(unit).subscribe(&m_unitDestroyEventHandler, &(p.first->m_unitPosInSet));
    p.first->m_unitDestroyID = unitManagerID;

    m_unitAddedEvent.raise(unit);
  }
  return p.second;
}

bool PersistentUnitGroup::insert(PersistentUnitGroup::const_iterator hint, BWAPI::Unit* unit)
{
#ifdef USE_SPAR_LOG
    if (!(unit->exists() && !BWAPI::isDestroyed(unit)))
    {
      SPAR_LOG(LogTypes.GENERAL_ERROR, "Error adding a destroyed or non-existing unit to a group: \"%s\"",
        toString(unit).c_str());
    }
#endif
  assert(unit->exists() && !BWAPI::isDestroyed(unit));

  UnitWrapperSet::iterator it = m_group.insert(hint, UnitWrapper(unit));

  it->m_unitPosInSet = it;
  PerceptualStateUnitData::OnIndividualUnitDestroy::SubscriberID unitManagerID = 
    BWAPI::getIndividualUnitDestroyEvent(unit).subscribe(&m_unitDestroyEventHandler, &(it->m_unitPosInSet));
  it->m_unitDestroyID = unitManagerID;

  m_unitAddedEvent.raise(unit);
  
  return true;
}

void PersistentUnitGroup::remove(const_iterator pos)
{
  BWAPI::Unit* unit = (*pos).getUnit();
  BWAPI::getIndividualUnitDestroyEvent(unit).unsubscribe((*pos).m_unitDestroyID);
  m_group.erase(pos);
  m_unitRemovedEvent.raise(unit);

  if(m_group.empty())
  {
    m_emptyEvent.raise();
  }
}