#include "viz/gauge.h"
#include "imgui.h"
#include <cmath>
#include <cstdio>

#ifndef M_PI
#define M_PI 3.14159265358979323846f
#endif

void gauge(const char* label, float value, float min_val, float max_val, float radius) {
    ImDrawList* draw_list = ImGui::GetWindowDrawList();
    ImVec2 pos = ImGui::GetCursorScreenPos();

    // Reserve space: diameter + label line
    float diameter = radius * 2.0f;
    ImGui::Dummy(ImVec2(diameter, diameter + ImGui::GetTextLineHeightWithSpacing()));

    ImVec2 center = ImVec2(pos.x + radius, pos.y + radius);

    // Arc spans 240 degrees: from 150deg to 390deg (i.e. 150 to 30 going clockwise)
    // In screen space Y is down, so angles go clockwise.
    // Start angle: 150 degrees = bottom-left, End angle: 390 = 30 degrees = bottom-right
    const float angle_start = (150.0f * (float)M_PI) / 180.0f;
    const float angle_end   = (390.0f * (float)M_PI) / 180.0f;
    const int   num_segments = 64;

    // Background arc (dark gray)
    ImU32 bg_color = IM_COL32(60, 60, 60, 220);
    for (int i = 0; i < num_segments; i++) {
        float a0 = angle_start + (angle_end - angle_start) * ((float)i       / num_segments);
        float a1 = angle_start + (angle_end - angle_start) * ((float)(i + 1) / num_segments);
        draw_list->AddLine(
            ImVec2(center.x + cosf(a0) * radius, center.y + sinf(a0) * radius),
            ImVec2(center.x + cosf(a1) * radius, center.y + sinf(a1) * radius),
            bg_color, 6.0f);
    }

    // Normalize value to [0, 1]
    float t = 0.0f;
    if (max_val > min_val) {
        t = (value - min_val) / (max_val - min_val);
        if (t < 0.0f) t = 0.0f;
        if (t > 1.0f) t = 1.0f;
    }

    // Color: green (t=0) -> yellow (t=0.5) -> red (t=1)
    float r, g, b;
    if (t < 0.5f) {
        float s = t * 2.0f;
        r = (unsigned char)(s * 255);
        g = 200;
        b = 0;
    } else {
        float s = (t - 0.5f) * 2.0f;
        r = 220;
        g = (unsigned char)((1.0f - s) * 200);
        b = 0;
    }
    ImU32 value_color = IM_COL32((int)r, (int)g, (int)b, 255);

    // Value arc
    float angle_value = angle_start + (angle_end - angle_start) * t;
    int value_segments = (int)(num_segments * t);
    for (int i = 0; i < value_segments; i++) {
        float a0 = angle_start + (angle_end - angle_start) * ((float)i       / num_segments);
        float a1 = angle_start + (angle_end - angle_start) * ((float)(i + 1) / num_segments);
        draw_list->AddLine(
            ImVec2(center.x + cosf(a0) * radius, center.y + sinf(a0) * radius),
            ImVec2(center.x + cosf(a1) * radius, center.y + sinf(a1) * radius),
            value_color, 6.0f);
    }

    // Needle: line from center to arc at current angle
    float needle_len = radius * 0.75f;
    ImVec2 needle_tip = ImVec2(
        center.x + cosf(angle_value) * needle_len,
        center.y + sinf(angle_value) * needle_len);
    draw_list->AddLine(center, needle_tip, IM_COL32(255, 255, 255, 240), 2.0f);
    draw_list->AddCircleFilled(center, 4.0f, IM_COL32(255, 255, 255, 200));

    // Value text centered
    char val_buf[32];
    snprintf(val_buf, sizeof(val_buf), "%.1f", value);
    ImVec2 val_size = ImGui::CalcTextSize(val_buf);
    draw_list->AddText(
        ImVec2(center.x - val_size.x * 0.5f, center.y + radius * 0.35f),
        IM_COL32(230, 230, 230, 255), val_buf);

    // Label below value
    ImVec2 label_size = ImGui::CalcTextSize(label);
    draw_list->AddText(
        ImVec2(center.x - label_size.x * 0.5f, center.y + radius * 0.35f + val_size.y + 2.0f),
        IM_COL32(180, 180, 180, 200), label);
}
