/*********************************************************************
 * \file   Singleton.hpp
 *
 * \author Romain BOULLARD
 * \date   October 2025
 *********************************************************************/
#ifndef BIGFOOT_UTILS_SINGLETON_HPP
#define BIGFOOT_UTILS_SINGLETON_HPP
#include <EASTL/optional.h>

namespace Bigfoot
{
template<class TYPE>
class Singleton
{
  public:
    Singleton() = delete;

    Singleton(const Singleton& p_singleton) = delete;
    Singleton(Singleton&& p_singleton) = delete;

    ~Singleton() = delete;

    /**
     * Get the instance.
     *
     * \return The instance
     */
    static constexpr TYPE& GetInstance()
    {
        return ms_instance.value();
    }

    /**
     * Is the instance initialized
     *
     * \return True if initialized, false otherwise
     */
    static constexpr bool HasInstance()
    {
        return ms_instance.has_value();
    }

    class Lifetime
    {
      public:
        /**
         * Constructor.
         *
         * \param p_args Arguments for the singleton
         */
        template<typename... ARGS>
        explicit Lifetime(ARGS&&... p_args)
        {
            Initialize(std::forward<ARGS>(p_args)...);
        }

        Lifetime(const Lifetime& p_lifetime) = delete;
        Lifetime(Lifetime&& p_lifetime) = delete;

        ~Lifetime()
        {
            Finalize();
        }

        Lifetime& operator=(const Lifetime& p_lifetime) = delete;
        Lifetime& operator=(Lifetime&& p_lifetime) noexcept = delete;
    };

    Singleton& operator=(const Singleton& p_singleton) = delete;
    Singleton& operator=(Singleton&& p_singleton) = delete;

  private:
    /**
     * Initialize the singleton.
     *
     * \param p_args Arguments for the singleton
     */
    template<typename... ARGS>
    static void Initialize(ARGS&&... p_args)
    {
        ms_instance.emplace(std::forward<ARGS>(p_args)...);
    }

    /**
     * Finalize the singleton.
     *
     */
    static void Finalize()
    {
        ms_instance.reset();
    }

    /**
     * The singleton.
     */
    inline static eastl::optional<TYPE> ms_instance;
};
}   // namespace Bigfoot
#endif
