// Demos faltantes: process_runner (Core), candlestick / gauge / heatmap /
// table_view (Viz). Aniade cobertura sobre los primitivos del registry que
// no tenian su entry en la gallery.

#include "demos.h"
#include "demo.h"

#include "core/process_runner.h"
#include "viz/candlestick.h"
#include "viz/gauge.h"
#include "viz/heatmap.h"
#include "viz/table_view.h"

#include <imgui.h>
#include <chrono>
#include <cmath>
#include <cstdio>
#include <thread>
#include <vector>

namespace gallery {

// ---------------------------------------------------------------------------
// process_runner (Core)
// ---------------------------------------------------------------------------

void demo_process_runner() {
    demo_header("process_runner", "v1.0.0",
        "Ejecuta una tarea en std::thread en background y expone estado thread-safe "
        "(idle/running/success/error). El widget runner_status() dibuja inline un "
        "spinner mientras corre y un mensaje de Success/Error al terminar.");

    static fn_ui::ProcessRunner runner;

    section("Tarea simulada (sleep 2s)");
    {
        if (ImGui::Button("Run task")) {
            if (!runner.is_busy()) {
                fn_ui::runner_trigger(runner, [](std::string& out) -> bool {
                    std::this_thread::sleep_for(std::chrono::seconds(2));
                    out = "task done in 2s";
                    return true;
                });
            }
        }
        ImGui::SameLine();
        if (ImGui::Button("Run failing task")) {
            if (!runner.is_busy()) {
                fn_ui::runner_trigger(runner, [](std::string& out) -> bool {
                    std::this_thread::sleep_for(std::chrono::seconds(1));
                    out = "simulated failure";
                    return false;
                });
            }
        }
        ImGui::SameLine();
        if (ImGui::Button("Reset")) runner.reset();
        fn_ui::runner_status(runner, "Working...");
    }

    code_block(
        "static fn_ui::ProcessRunner r;\n"
        "if (button(\"Run\", Primary) && !r.is_busy()) {\n"
        "    fn_ui::runner_trigger(r, [](std::string& out) -> bool {\n"
        "        return do_work(&out);\n"
        "    });\n"
        "}\n"
        "fn_ui::runner_status(r, \"Working...\");"
    );
}

// ---------------------------------------------------------------------------
// candlestick (Viz)
// ---------------------------------------------------------------------------

void demo_candlestick() {
    demo_header("candlestick", "v1.0.0",
        "Grafico de velas OHLC con ImPlot custom rendering. Verde si close >= open, "
        "rojo si bajista. Tooltip al hover muestra OHLC del dia.");

    section("OHLC sintetico (30 dias)");
    {
        static std::vector<double> dates, opens, closes, lows, highs;
        if (dates.empty()) {
            dates.reserve(30); opens.reserve(30); closes.reserve(30);
            lows.reserve(30);  highs.reserve(30);
            double price = 100.0;
            for (int i = 0; i < 30; ++i) {
                double drift  = std::sin(i * 0.4) * 1.2;
                double o      = price;
                double c      = price + drift + (i % 3 == 0 ? -0.6 : 0.4);
                double l      = std::min(o, c) - 0.8 - (i % 5) * 0.1;
                double h      = std::max(o, c) + 0.8 + (i % 4) * 0.1;
                dates.push_back(double(i));
                opens.push_back(o);
                closes.push_back(c);
                lows.push_back(l);
                highs.push_back(h);
                price = c;
            }
        }
        candlestick("##cs", dates.data(), opens.data(), closes.data(),
                    lows.data(), highs.data(), int(dates.size()));
    }

    code_block(
        "candlestick(\"##cs\", dates, opens, closes, lows, highs, n,\n"
        "            /*width_percent=*/0.25f, /*tooltip=*/true);"
    );
}

// ---------------------------------------------------------------------------
// gauge (Viz)
// ---------------------------------------------------------------------------

void demo_gauge() {
    demo_header("gauge", "v1.0.0",
        "Indicador circular tipo velocimetro con ImGui DrawList. Color interpolado "
        "verde -> amarillo -> rojo segun el valor normalizado.");

    static float v_cpu = 0.32f, v_mem = 0.78f, v_gpu = 0.55f;

    section("Tres gauges con sliders");
    {
        ImGui::SliderFloat("cpu",  &v_cpu,  0.0f, 1.0f);
        ImGui::SliderFloat("mem",  &v_mem,  0.0f, 1.0f);
        ImGui::SliderFloat("gpu",  &v_gpu,  0.0f, 1.0f);

        ImGui::Spacing();
        ImGui::BeginGroup();
        gauge("CPU", v_cpu, 0.0f, 1.0f, 60.0f);
        ImGui::EndGroup();
        ImGui::SameLine(0.0f, 24.0f);
        ImGui::BeginGroup();
        gauge("MEM", v_mem, 0.0f, 1.0f, 60.0f);
        ImGui::EndGroup();
        ImGui::SameLine(0.0f, 24.0f);
        ImGui::BeginGroup();
        gauge("GPU", v_gpu, 0.0f, 1.0f, 60.0f);
        ImGui::EndGroup();
    }

    code_block("gauge(\"CPU\", 0.32f, 0.0f, 1.0f, 60.0f);");
}

// ---------------------------------------------------------------------------
// heatmap (Viz)
// ---------------------------------------------------------------------------

void demo_heatmap() {
    demo_header("heatmap", "v1.0.0",
        "Mapa de calor 2D con ImPlot. Datos row-major. Util para correlation "
        "matrices, attention maps, distribuciones 2D discretas.");

    constexpr int R = 12;
    constexpr int C = 12;
    static float values[R * C] = {0};
    static bool  init = false;
    if (!init) {
        for (int r = 0; r < R; ++r) {
            for (int c = 0; c < C; ++c) {
                float dx = (c - C * 0.5f) / float(C);
                float dy = (r - R * 0.5f) / float(R);
                values[r * C + c] = std::exp(-(dx * dx + dy * dy) * 6.0f);
            }
        }
        init = true;
    }

    section("Gaussian 12x12");
    {
        heatmap("##hm", values, R, C, 0.0f, 1.0f);
    }

    code_block(
        "float values[R * C];\n"
        "// fill row-major: values[r * C + c] = ...\n"
        "heatmap(\"##hm\", values, R, C, /*min=*/0.0f, /*max=*/1.0f);"
    );
}

// ---------------------------------------------------------------------------
// table_view (Viz)
// ---------------------------------------------------------------------------

void demo_table_view() {
    demo_header("table_view", "v1.0.0",
        "Tabla interactiva con sorting indicators y scroll usando la ImGui Tables API. "
        "Headers + cells row-major. Util para dashboards y inspectores.");

    section("Lenguajes del registry");
    {
        const char* headers[] = {"id", "lang", "domain", "purity"};
        // 6 filas x 4 cols, row-major
        const char* cells[] = {
            "filter_slice_go_core",       "go",  "core",     "pure",
            "metabase_setup_py_infra",    "py",  "infra",    "impure",
            "rsync_deploy_bash_infra",    "sh",  "infra",    "impure",
            "button_cpp_core",            "cpp", "core",     "pure",
            "gl_texture_load_cpp_gfx",    "cpp", "gfx",      "impure",
            "audio_fft_cpp_core",         "cpp", "core",     "pure",
        };
        const int row_count = 6;
        const int col_count = 4;
        table_view("##tbl", headers, col_count, cells, row_count);
    }

    code_block(
        "const char* headers[] = {\"id\", \"lang\", \"domain\"};\n"
        "const char* cells[]   = {/* row-major: r0c0,r0c1,r0c2, r1c0,... */};\n"
        "table_view(\"##tbl\", headers, 3, cells, n_rows);"
    );
}

} // namespace gallery
