#ifdef _DEBUG_COMPONENT
#include "Tracked.h"
#include <functional>
#include <algorithm>
#include <set>

const Tracked* Tracked::s_tail = NULL;

bool Tracked::_setDebugInfo() const
{
  bool set = !m_debugInfoSet;
  if (set)
  {
    m_debugName = toString(this);
    m_debugInfoSet = true;
  }
#ifdef _DEBUG
  else
  {
    const Tracked* previous = Tracked::_getPrevious(this);
    assert(previous == NULL || previous->m_debugInfoSet);
  }
#endif
  return set;
}

void printTrackedObjects()
{
  std::cout << "Tracked objects" << std::endl;
  std::cout << "---------------" << std::endl;
  const Tracked* tracked = Tracked::_getTail();
  while (tracked != NULL)
  {
    std::cout << std::hex << tracked << " " << tracked->m_debugName;
    std::cout << std::endl;
    tracked = Tracked::_getPrevious(tracked);
  }
  std::cout << std::endl;
}

void Tracked::_setComponentsDebugInfo()
{
  const Tracked* tracked = Tracked::_getTail();
  while (tracked != NULL && tracked->_setDebugInfo())
  {
    tracked = Tracked::_getPrevious(tracked);
  }

  //if (BWAPI::Broodwar->getFrameCount() % 200)
  //  printComponents();
}

struct make_pair : public std::unary_function<const Tracked*, std::pair<const Tracked*, const type_info*>>
{
  std::pair<const void*, const type_info*> operator()(const Tracked* p) const
  {
    return std::make_pair(p, &typeid(p));
  }
};

struct Comparison
{
  template <class First>
  bool operator()(const std::pair<const First*, const type_info*>& p1, const std::pair<const First*, const type_info*>& p2) const
  {
    return p1.first < p2.first;
  }
};

size_t Tracked::_signalMemoryLeaks()
{
  std::cout << std::endl << "Checking for memory leaks (tracked objects only)..." << std::endl;
  size_t nbLeakedObjects = 0;
  const Tracked* object = Tracked::s_tail;
  while (object != NULL)
  {
    ++nbLeakedObjects;

    std::cout << "\"";
    try
    {
      if (object->m_debugInfoSet)
        std::cout << object->m_debugName;
      else
        std::cout << *object;
    }
    catch (...) {}
    std::cout << " (" << typeid(*object).name() << " 0x" << std::hex << static_cast<const void*>(object) << ")";
    std::cout << "\"";

    object = Tracked::_getPrevious(object);
  }

  std::cout << std::endl;

  return nbLeakedObjects;
}

#endif