#pragma once
#include <cstdint>

// Render de etiquetas de nodos sobre el viewport del grafo (issue 0049j).
// Independiente del renderer GPU: usa `ImDrawList` del current window y se
// compone sobre la imagen del FBO ya pintada por `graph_renderer`.

struct GraphData;
struct GraphViewportState;

namespace graph {

struct LabelPolicy {
    bool  always_for_selected   = true;
    bool  always_for_hovered    = true;
    bool  always_for_pinned     = false;
    int   max_visible           = 200;     // top-N por size + degree
    float min_zoom_for_all      = 4.0f;    // a este zoom, mostrar todos los visibles del viewport
    float min_node_pixel_size   = 12.0f;   // skip si en pantalla mide menos
    float font_size             = 13.0f;   // pixels
    uint32_t color              = 0xFFFFFFFF; // ABGR
    uint32_t bg_color           = 0xC8000000; // semi-transparente
    float padding_x             = 4.0f;
    float padding_y             = 2.0f;
};

// Callback que devuelve el texto del label dado un node_idx. El consumer
// maneja su propio string pool / metadata. Devolver NULL o "" omite el label.
typedef const char* (*GetLabelFn)(int node_idx, void* user);

// Llamar tras `ImGui::Image(...)` del FBO (o tras `graph_viewport`). Usa
// `ImGui::GetItemRectMin/Max()` para conocer el rect del widget y
// `ImGui::GetWindowDrawList()` para pintar.
void graph_labels_draw(const GraphData& graph, const GraphViewportState& state,
                       const LabelPolicy& policy, GetLabelFn cb, void* user);

// Variante sin ImGui state — util para tests y para callers que ya tienen
// el widget rect resuelto. Pinta sobre el ImDrawList del current window.
// `widget_min_x/y` y `widget_w/h` describen el rect del FBO en pantalla.
void graph_labels_draw_at(const GraphData& graph,
                          float cam_x, float cam_y, float zoom,
                          float widget_min_x, float widget_min_y,
                          float widget_w, float widget_h,
                          const LabelPolicy& policy,
                          GetLabelFn cb, void* user);

// --- Helpers puros (exportados para tests y callers avanzados) -----------

// Calcula el grado (numero de aristas incidentes) por nodo. El caller
// reserva `out_degrees` con tamano `graph.node_count`.
void graph_compute_degrees(const GraphData& graph, int* out_degrees);

// Selecciona los indices de nodos que deberian recibir label segun la
// politica. Funcion pura: no toca ImGui ni el grafo. Devuelve el numero de
// indices escritos en `out_indices` (capado a `out_capacity`).
//
// `degrees` puede ser NULL — en ese caso el score de top-N degrada a `size`
// (sin el factor degree+1).
int graph_labels_select(const GraphData& graph, const LabelPolicy& policy,
                        float cam_x, float cam_y, float zoom,
                        float widget_w, float widget_h,
                        const int* degrees,
                        int* out_indices, int out_capacity);

} // namespace graph
