// AudioInfo.cpp
#include "AudioInfo.h"
#include "../../core/utils/EngineConfig.h"
#include <imgui.h>
#include "../../core/audio/AudioEngine.h"
#include "../../core/utils/Profiler.h"
#include <cmath>
#include <algorithm>


void DrawAudioPlayingList()
{
    PROFILE_ENGINE_SCOPE("Engine::DrawAudioPlayingList");
    if (!g_engineConfig.settings.show_audio_window)
        return;

    ImGui::SetNextWindowSize(ImVec2(240, 180), ImGuiCond_FirstUseEver);
    ImGui::Begin("Audio Output");

    const auto& masterVU = AudioEngine::GetMasterVU();
    size_t      nCh      = masterVU.size();
    if (nCh == 0)
    {
        ImGui::TextDisabled("No audio channels");
        ImGui::End();
        return;
    }

    // per-channel smoothing & peak-hold
    static std::vector<float> smooth, peakHold, decay;
    if (smooth.size() != nCh) {
        smooth.assign(nCh,    0.0f);
        peakHold.assign(nCh,  0.0f);
        decay.assign(nCh,     0.005f);
    }

    // layout: compute barW clamped to maxBarW, but no centering
    float availW       = ImGui::GetContentRegionAvail().x;
    const float space  = 2.0f;
    const float maxBar = 40.0f;  // maximum bar width
    float idealBarW    = (availW - (nCh - 1)*space) / float(nCh);
    float barW         = std::min(idealBarW, maxBar);
    float barH         = (ImGui::GetContentRegionAvail().y * 0.90) - 25.0f;

    ImVec2      origin = ImGui::GetCursorScreenPos();
    ImDrawList* dl     = ImGui::GetWindowDrawList();

    // reserve the area for all bars + labels
    ImGui::Dummy(ImVec2(availW, barH + 20));
    ImGui::SameLine();
    ImGui::NewLine();

    for (size_t ch = 0; ch < nCh; ++ch)
    {
        float raw = masterVU[ch];

        // smoothing & peak-hold
        smooth[ch]   = 0.1f * raw + 0.9f * smooth[ch];
        peakHold[ch] = std::max(peakHold[ch], smooth[ch]);
        peakHold[ch] = std::max(0.0f, peakHold[ch] - decay[ch]);

        // clamp & normalized value
        float v    = std::clamp(smooth[ch], 0.0f, 1.0f);
        bool  clip = (v >= 1.0f);

        // compute dB for display
        float amp  = std::max(v, 1e-5f);
        float dB   = 20.0f * log10f(amp);
        float norm = std::clamp((dB + 80.0f)/80.0f, 0.0f, 1.0f);

        // choose solid color by dBFS thresholds
        ImU32 fillCol;
        if (dB <= -12.0f) {
            fillCol = IM_COL32(0,255,0,255);   // green :contentReference[oaicite:8]{index=8}
        } else if (dB <= -2.0f) {
            fillCol = IM_COL32(255,255,0,255); // yellow :contentReference[oaicite:9]{index=9}
        } else {
            fillCol = IM_COL32(255,0,0,255);   // red (warning) :contentReference[oaicite:10]{index=10}
        }
        clip = (dB >= 0.0f);               // true clipping at ≥0 dBFS :contentReference[oaicite:11]{index=11}
        ImU32 bgCol = IM_COL32(50,50,50,200);

        // compute bar rectangle (left-aligned)
        float x0 = origin.x + ch * (barW + space);
        float y0 = origin.y;
        float x1 = x0 + barW;
        float y1 = y0 + barH;

        // drop-shadow
        dl->AddRectFilled({x0+2, y0+2}, {x1+2, y1+2}, IM_COL32(0,0,0,80), 3.0f);
        // background (rounded corners)
        dl->AddRectFilled({x0, y0}, {x1, y1}, bgCol, 3.0f);
        // solid level fill
        float fy = y1 - v*barH;
        dl->AddRectFilled({x0, fy}, {x1, y1}, fillCol, 3.0f);
        // peak-hold line
        float py = y1 - peakHold[ch] * barH;
        dl->AddLine({x0, py}, {x1, py}, IM_COL32(255,255,255,180), 2.0f);
        if (clip)
            dl->AddCircleFilled({x0 + barW*0.5f, y0 - 6}, 4.0f, IM_COL32(255,0,0,255));

        char buf[16];
        snprintf(buf, sizeof(buf), "CH%zu", ch+1);
        float tx = x0 + (barW - ImGui::CalcTextSize(buf).x)*0.5f;
        dl->AddText({tx, y1 + 2}, IM_COL32(200,200,200,255), buf);

        snprintf(buf, sizeof(buf), "%.0fdb", dB);
        tx = x0 + (barW - ImGui::CalcTextSize(buf).x)*0.5f;
        dl->AddText({tx, y1 + 14}, IM_COL32(255,255,255,200), buf);
    }

    ImGui::End();
}
