// demos_3d — demos para los primitivos viz/* basados en ImPlot3D.
// Issue 0028: surface_plot_3d real + scatter_3d.

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

#include "viz/surface_plot_3d.h"
#include "viz/scatter_3d.h"

#include <imgui.h>
#include <cmath>
#include <random>
#include <vector>

namespace gallery {

// ---------------------------------------------------------------------------
// surface_plot_3d
// ---------------------------------------------------------------------------

void demo_surface_plot_3d() {
    demo_header("surface_plot_3d", "v2.0.0",
        "Superficie 3D ImPlot3D (z = A * sin(fx*x) * cos(fy*y)) con sliders para "
        "ajustar las frecuencias en tiempo real. Drag para orbitar, wheel para zoom.");

    section("Malla 64x64 — sin(fx*x) * cos(fy*y)");

    static float fx = 0.20f;
    static float fy = 0.20f;
    static float amp = 1.0f;

    ImGui::SliderFloat("fx", &fx, 0.05f, 1.0f, "%.2f");
    ImGui::SliderFloat("fy", &fy, 0.05f, 1.0f, "%.2f");
    ImGui::SliderFloat("amplitud", &amp, 0.1f, 3.0f, "%.2f");

    constexpr int N = 64;
    static std::vector<float> z(N * N);
    for (int j = 0; j < N; ++j) {
        for (int i = 0; i < N; ++i) {
            z[j * N + i] = amp * std::sin(fx * float(i)) * std::cos(fy * float(j));
        }
    }

    fn::SurfacePlot3DConfig cfg{};
    cfg.z = z.data();
    cfg.nx = N; cfg.ny = N;
    cfg.x_min = 0.f; cfg.x_max = float(N);
    cfg.y_min = 0.f; cfg.y_max = float(N);
    cfg.size = ImVec2(-1.f, 420.f);
    fn::surface_plot_3d("##gallery_surface", cfg);
}

// ---------------------------------------------------------------------------
// scatter_3d
// ---------------------------------------------------------------------------

void demo_scatter_3d() {
    demo_header("scatter_3d", "v1.0.0",
        "Scatter 3D ImPlot3D con color por punto. 3 clusters gaussianos sinteticos "
        "(N=500) para simular una visualizacion tipica de PCA / clustering.");

    section("3 clusters gaussianos (500 puntos)");

    constexpr int N = 500;
    static std::vector<float> xs(N), ys(N), zs(N);
    static std::vector<ImU32> colors(N);
    static bool initialized = false;

    if (!initialized) {
        std::mt19937 rng(42);
        std::normal_distribution<float> g(0.f, 0.4f);
        const ImU32 palette[3] = {
            IM_COL32(255,  99,  71, 255),  // tomate
            IM_COL32( 65, 170, 255, 255),  // azul
            IM_COL32(120, 220, 120, 255),  // verde
        };
        const float cx[3] = {-1.5f, 1.5f, 0.f};
        const float cy[3] = { 0.f,  0.f,  2.0f};
        const float cz[3] = { 0.f,  1.0f,-1.0f};
        for (int i = 0; i < N; ++i) {
            int c = i % 3;
            xs[i] = cx[c] + g(rng);
            ys[i] = cy[c] + g(rng);
            zs[i] = cz[c] + g(rng);
            colors[i] = palette[c];
        }
        initialized = true;
    }

    fn::Scatter3DConfig cfg{};
    cfg.xs = xs.data();
    cfg.ys = ys.data();
    cfg.zs = zs.data();
    cfg.colors = colors.data();
    cfg.n = N;
    cfg.size = ImVec2(-1.f, 420.f);
    fn::scatter_3d("##gallery_clusters", cfg);
}

} // namespace gallery
