#pragma once
class ISystem {
public:
    virtual void Init() = 0;
    virtual void LateInit() {};
    virtual void EarlyShutdown() {};
    virtual void Shutdown() = 0;
    virtual ~ISystem() = default;
};
template <typename T>
class ISingleton : public ISystem{
protected:
    inline static T* ms_Singleton = nullptr;
public:
    explicit ISingleton() {
        ms_Singleton = static_cast<T*>(this);
    }
    ~ISingleton() {
        ms_Singleton = nullptr;
    }
    static constexpr T& GetSingleton(void) {
        return *ms_Singleton;
    }
    static constexpr T* GetSingletonPtr(void) {
        return ms_Singleton;
    }
public:
    void Init() override = 0;
    void Shutdown()override = 0;
};
template <typename T>
class Singleton{
protected:
    inline static T* ms_Singleton = nullptr;
public:
    explicit Singleton() {
        ms_Singleton = static_cast<T*>(this);
    }
    ~Singleton() {
        ms_Singleton = nullptr;
    }
    static constexpr T& GetSingleton(void) {
        return *ms_Singleton;
    }
    static constexpr T* GetSingletonPtr(void) {
        return ms_Singleton;
    }
};