#pragma once
#include "../../Utils/ReferenceCounted.h"
#include "Component.h"

/**
 * @brief Reference-counted components are zombified instead of being deleted right away when their 
 *        reference counter hits 0.
 */
class ReferenceCountedComponent : public virtual Component, public ReferenceCounted
{
public:
  ReferenceCountedComponent()
    : Component()
    , ReferenceCounted()
  {}

  ReferenceCountedComponent(const ReferenceCountedComponent& other)
    : Component(other)
    , ReferenceCounted(other)
  {}

  template <class Acquirer>
  void acquire(const Acquirer *acquirer) const
  {
    ReferenceCounted::acquire(acquirer);
  }

  /**
   * @brief Releases the acquisition made by a previous acquirer, which decrements this reference count.
   *        If the counter reaches 0, the instance is zombified.
   * @tparam Acquirer Type of acquirer.
   * @param acquirer The object which previously acquired this reference-counted instance.
   */
  template <class Acquirer>
  void release(const Acquirer *acquirer) const
  {
    ReferenceCounted::_removeAcquirer(acquirer);

    if (--m_nbRef == 0)
      Component::addZombieComponent(this);
  }

protected:
  template <class ReferenceCounted>
  friend class AutoPtr;

  template <class Acquirer>
  static const void* _convertToVoidPtr(const Acquirer* acquirer)
  {
    return ReferenceCounted::_convertToVoidPtr(acquirer);
  }
};
