#pragma once

#include <atomic>
#include <cstdint>
#include <mutex>
#include <thread>

namespace ta::bootstrap
{
    class RuntimeHost;
}

namespace ta::application::runtime
{
    enum class RuntimePhase : std::uint8_t
    {
        None,
        Starting,
        Running,
        Stopping,
        Stopped,
        Failed
    };

    class RuntimeState final
    {
    public:
        RuntimeState() = default;

        [[nodiscard]] RuntimePhase phase() const noexcept;
        [[nodiscard]] bool is_terminal() const noexcept;
        [[nodiscard]] bool should_accept_callbacks() const noexcept;
        void mark_application_update_thread() noexcept;
        void clear_application_update_thread() noexcept;
        [[nodiscard]] bool is_application_update_thread() const noexcept;

    private:
        friend class ta::bootstrap::RuntimeHost;

        void set_phase(RuntimePhase phase) noexcept;

        std::atomic<RuntimePhase> phase_{ RuntimePhase::None };
        mutable std::mutex application_thread_mutex_;
        std::thread::id application_thread_id_{};
    };

    [[nodiscard]] RuntimeState& state() noexcept;
    [[nodiscard]] bool should_accept_callbacks() noexcept;
    void mark_application_update_thread() noexcept;
    void clear_application_update_thread() noexcept;
    [[nodiscard]] bool is_application_update_thread() noexcept;
    [[nodiscard]] const char* phase_name(RuntimePhase phase) noexcept;
}
