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

namespace fn::gfx {

enum class DagKind { Gen, Op, Blend, Output };

// Param indices for a control reference floats inside the node's own block
// (range 0..param_count-1). Up to 3 indices are used (Color uses 3 contiguous,
// XY uses 2 contiguous, Slider uses 1).
struct DagControl {
    enum class Kind { Slider, XY, Color };
    Kind kind;
    std::string label;
    std::array<int, 3> param_idx{-1, -1, -1};
    float min = 0.0f;
    float max = 1.0f;
    float step = 0.0f;
};

struct DagNodeDef {
    std::string name;
    std::string label;
    std::string desc;
    DagKind kind = DagKind::Gen;
    int num_inputs = 0; // 0=Gen, 1=Op, 2=Blend, up to 4
    std::vector<std::string> param_names;
    std::vector<float>       param_defaults;
    std::vector<DagControl>  controls;
    // body_glsl receives the base vec4 index where this node's params live in
    // the global u_params[] array (0 if param_count == 0; same value for nodes
    // that fit in a single vec4).
    std::function<std::string(int base_vec4)> body_glsl;
    bool is_builtin = true; // user-saved generators set this false
};

struct DagStep {
    std::string id;
    std::string name;
    std::vector<float> params;                                 // size == def->param_defaults.size()
    std::array<std::string, 4> source_ids{"", "", "", ""};      // up to 4 inputs; "" = no connection
    float editor_pos_x = 0.0f;
    float editor_pos_y = 0.0f;
    uint32_t editor_uid = 0; // monotonic counter, used as node editor ID
    bool preview_open = false; // show in-node thumbnail of out_<index>
};

// Number of vec4 slots a node with `param_count` floats occupies. 0 -> 0.
inline int dag_vec4_count(int param_count) {
    if (param_count <= 0) return 0;
    return (param_count + 3) / 4;
}

} // namespace fn::gfx
