#include "stdafx.h"
#include "../../SparAIContainer.h"
#include "../PerceptualState.h"
#include "UnitTypeObject.h"
#include "CurrentWorld.h"

UnitTypeObject::UnitTypeObject(BWAPI::UnitType unitType, planning::PrimitiveType* type)
  : SparObject(unitType.getName(), type)
  , m_unitType(unitType)
  , m_unitTypeCreatable(*this, NULL)
  , m_unitTypeInstanceCompleted(*this, new UnitTypeInstanceCompleted(this))
{
  CurrentWorld::addUnitTypeObject(this);
}

void UnitTypeObject::initialize()
{
  SparObject::initialize();

  m_cachedOneCompleted = m_unitTypeInstanceCompleted->evaluate(CurrentWorld::getInstance(), planning::Bindings::emptyBindings());

  m_unitTypeCreatable = new UnitTypeCreatable(this);
  assert(m_unitTypeInstanceCompleted != NULL);
  m_cachedIsCreatable = m_unitTypeCreatable->evaluate(CurrentWorld::getInstance(), planning::Bindings::emptyBindings());

  if (m_cachedIsCreatable)
  {
    CurrentWorld::raiseUnitTypeCreatableChangedEvent(this);
  } 
  if (m_cachedOneCompleted)
  {
    CurrentWorld::raiseUnitTypeCompletedChangedEvent(this);
  }

#ifdef USE_SPAR_LOG
  std::cout << "  IsCreatable iif \"" << *m_unitTypeCreatable << "\"" << std::endl;
  std::cout << "  InstanceCompleted iif \"" << *m_unitTypeInstanceCompleted << std::endl;
#endif
}

UnitTypeObject::~UnitTypeObject()
{
  releaseMembers();
}

void UnitTypeObject::releaseMembers()
{
  // This releases the references
  m_unitTypeCreatable = NULL;
  m_unitTypeInstanceCompleted = NULL;

  SparObject::releaseMembers();
}

void UnitTypeObject::update()
{
  // TODO: getNbCompletedOwnUnits(Archon) returns > 0 even if Archon is morphing,
  //       no field in BWAPI to indicate it is morphing - BWAPI bug?

  //const size_t nb = Spar->getPerceptualState()->getMap()->getNbCompletedOwnUnits(m_unitType);
  //if (m_cachedOneCompleted && nb == 0)
  //{
  //  m_cachedOneCompleted = false;
  //  CurrentWorld::raiseUnitTypeCompletedChangedEvent(this);
  //  updateOutgoingDependencies();
  //}
  //else if (!m_cachedOneCompleted && nb > 0)
  //{
  //  m_cachedOneCompleted = true;
  //  CurrentWorld::raiseUnitTypeCompletedChangedEvent(this);
  //  updateOutgoingDependencies();
  //}

  //const bool creatable = m_unitTypeCreatable->evaluate(CurrentWorld::getInstance(), planning::Bindings::emptyBindings());
  //if (m_cachedIsCreatable && !creatable)
  //{
  //  m_cachedIsCreatable = false;
  //  CurrentWorld::raiseUnitTypeCreatableChangedEvent(this);
  //  updateOutgoingDependencies();
  //}
  //else if (!m_cachedIsCreatable && creatable)
  //{
  //  m_cachedIsCreatable = true;
  //  CurrentWorld::raiseUnitTypeCreatableChangedEvent(this);
  //  updateOutgoingDependencies();
  //}

  {
    bool oldValue = m_cachedIsCreatable;
    if ((m_cachedIsCreatable = m_unitTypeCreatable->evaluate(CurrentWorld::getInstance(), planning::Bindings::emptyBindings()))
      != oldValue)
    {
      CurrentWorld::raiseUnitTypeCreatableChangedEvent(this);
      updateOutgoingDependencies();
    }
  }
  {
    bool oldValue = m_cachedOneCompleted;
    if ((m_cachedOneCompleted = m_unitTypeInstanceCompleted->evaluate(CurrentWorld::getInstance(), planning::Bindings::emptyBindings()))
      != oldValue)
    {
      CurrentWorld::raiseUnitTypeCompletedChangedEvent(this);
      updateOutgoingDependencies();
    }
  }
}