#pragma once
#include <cstdint>

// --- Graph node ---
struct GraphNode {
    uint32_t id;
    float x, y;            // position in layout space
    float vx, vy;          // velocity (used by force layout)
    float size;             // visual radius (default 4.0)
    uint32_t color;         // ABGR packed (0 = use default palette)
    const char* label;      // optional display label (nullptr = none)
    uint32_t community;     // group/cluster ID (for auto-coloring)
    float value;            // arbitrary metric (for sizing)
    bool pinned;            // if true, force layout won't move this node
};

// --- Graph edge ---
struct GraphEdge {
    uint32_t source;        // index into GraphData::nodes
    uint32_t target;        // index into GraphData::nodes
    float weight;           // edge weight (affects attraction force)
    uint32_t color;         // ABGR packed (0 = default gray)
};

// --- Graph container ---
struct GraphData {
    GraphNode* nodes;
    int node_count;
    GraphEdge* edges;
    int edge_count;

    // Bounding box (updated by layout)
    float min_x, min_y, max_x, max_y;

    // Recompute bounding box from node positions
    void update_bounds();

    // Find node index by id. Returns -1 if not found.
    int find_node(uint32_t id) const;
};

// --- Helper: create a default node ---
inline GraphNode graph_node(uint32_t id, float x = 0, float y = 0) {
    return {id, x, y, 0, 0, 4.0f, 0, nullptr, 0, 0, false};
}

// --- Helper: create an edge ---
inline GraphEdge graph_edge(uint32_t source, uint32_t target, float weight = 1.0f) {
    return {source, target, weight, 0};
}
