#pragma once

#include "game_object.hpp"
#include "utils/ptr.hpp"

#include <memory>       // unique_ptr
#include <utility>      // move
#include <algorithm>    // remove_if, for_each
#include <vector>


namespace frog
{


class engine;


class scene
{
    std::vector<ptr<game_object>> objects;

    template <typename Self, typename Func>
    static void for_each_impl(Self& self, Func func)
    {
        std::for_each(self.objects.begin(), self.objects.end(),
            [=](auto& ptr)
        {
            if (ptr)
                func(*ptr);
        });
    }

public:
    void add(ptr<game_object> obj)
    {
        objects.push_back(std::move(obj));
    }

    void init(engine&);

    void stable_update(engine&);

    void frame_update(engine&);

    void cleanup(engine&);

    template<typename Func>
    void for_each_object(Func func) const { for_each_impl(*this, func); }

    template<typename Func>
    void for_each_object(Func func)       { for_each_impl(*this, func); }
};


} // namespace frog
