#pragma once
#include <functional>
#include <vector> 

namespace zecsy
{
    class system_scheduler final
    {
    public:
        void add_system(float freq, auto&& func);

        void add_system(int freq, auto&& func);

        void update(float dt);

    private:
        struct system_handler
        {
            double interval;
            double accumulator = 0.0f;
            std::function<void(float)> callback;
        };

        std::vector<system_handler> systems;
    };

    inline void system_scheduler::add_system(float freq, auto&& func)
    {
        systems.emplace_back(1.0f / freq, 0.0f,
                             std::forward<decltype(func)>(func));
    }

    inline void system_scheduler::add_system(int freq, auto&& func)
    {
        add_system(float(freq), func);
    }

    inline void system_scheduler::update(float dt)
    {
        dt = std::max(0.0f, dt);

        for(auto& s: systems)
        {
            s.accumulator += dt;
            while(s.accumulator >= s.interval)
            {
                s.callback(dt);
                s.accumulator -= s.interval;
            }
        }
    }
} // namespace zecsy