#pragma once
#include <functional>
#include <string>
#include <string_view>
#include <unordered_map>
#include <variant>
#include "renderive/render_graph/Render_Plan.hpp"
#include "renderive/scene/base/Render_Contexts.hpp"

using Prepare_Render_Node_Function = std::function<void(const Prepare_Render_Context&)>;
using Paint_Render_Node_Function = std::function<void(const Paint_Render_Context&)>;
using Render_Node_Function = std::variant<Prepare_Render_Node_Function,
                                          Paint_Render_Node_Function>;

struct Renderable_Graph {
    Render_Graph graph;
    std::vector<Render_Node_Function> functions;
};

class Renderable_Graph_Builder {
public:
    using Task = Render_Graph_Builder::Task;
    using Node_Id_Resolver = std::function<Render_Node_Id(std::string_view)>;
    Renderable_Graph_Builder(std::uint64_t owner_id, Node_Id_Resolver resolve_node_id);
    Task emplace(std::string logical_key, std::string name,
                 Prepare_Render_Node_Function function);
    Task emplace(std::string logical_key, std::string name,
                 Paint_Render_Node_Function function);
    void precede(Task from, Task to);
    [[nodiscard]] Task find(std::string_view logical_key) const;
    [[nodiscard]] Renderable_Graph finish() &&;
private:
    std::uint64_t owner_id_{};
    Node_Id_Resolver resolve_node_id_;
    Render_Graph_Builder builder_;
    std::unordered_map<std::string, Task> tasks_;
    std::unordered_map<Render_Node_Id, Render_Node_Function> functions_;

    Task emplace_function(std::string logical_key, std::string name,
                          Render_Node_Kind kind, Render_Node_Function function);
};
