#pragma once

#include <vector>

#include "application/contracts/IApplicationTick.h"
#include "application/contracts/IGameTick.h"
#include "foundation/diagnostics/CrashDiagnostics.h"

namespace ta::application
{
    class ApplicationTickScheduler final
    {
    public:
        void add(const char* name, IApplicationTick& participant)
        {
            participants_.push_back({name, &participant});
        }

        void tick()
        {
            for (const Participant& participant : participants_)
            {
                ta::foundation::diagnostics::crash::set_stage(participant.name);
                participant.value->on_application_tick();
            }
            ta::foundation::diagnostics::crash::set_stage("runtime.application.ticks.complete");
        }

    private:
        struct Participant final
        {
            const char* name = "runtime.application.tick.unknown";
            IApplicationTick* value = nullptr;
        };

        std::vector<Participant> participants_;
    };

    class GameTickScheduler final
    {
    public:
        void add(const char* name, IGameTick& participant)
        {
            participants_.push_back({name, &participant});
        }

        void tick()
        {
            for (const Participant& participant : participants_)
            {
                ta::foundation::diagnostics::crash::set_stage(participant.name);
                participant.value->on_game_tick();
            }
            ta::foundation::diagnostics::crash::set_stage("runtime.game.ticks.complete");
        }

    private:
        struct Participant final
        {
            const char* name = "runtime.game.tick.unknown";
            IGameTick* value = nullptr;
        };

        std::vector<Participant> participants_;
    };
}
