// DragonX Wallet - ImGui Edition
// Copyright 2024-2026 The Hush Developers
// Released under the GPLv3

#include "notifications.h"
#include "schema/ui_schema.h"
#include "material/type.h"
#include "material/draw_helpers.h"
#include "../embedded/IconsMaterialDesign.h"
#include "imgui.h"

namespace dragonx {
namespace ui {

void Notifications::render()
{
    // Remove expired notifications
    while (!notifications_.empty() && notifications_.front().isExpired()) {
        notifications_.pop_front();
    }
    
    if (notifications_.empty()) {
        return;
    }
    
    // Only show the most recent (last) notification as a compact status-bar pill
    const auto& notif = notifications_.back();

    const auto& S = schema::UI();
    auto nde = [&](const char* key, float fb) {
        float v = S.drawElement("components.notifications", key).size;
        return v >= 0 ? v : fb;
    };

    // Status bar geometry. These are logical-px schema values; the icon/text drawn into the pill
    // are DPI-baked, so scale the box by dpiScale to match the (also DPI-scaled) rendered status bar
    // and keep the icon/text inside the pill at HiDPI.
    const float dp = Layout::dpiScale();
    float sbHeight = S.window("components.status-bar").height * dp;
    if (sbHeight <= 0.0f) sbHeight = 30.0f * dp;

    ImGuiViewport* viewport = ImGui::GetMainViewport();
    float viewBottom = viewport->WorkPos.y + viewport->WorkSize.y;
    float viewCenterX = viewport->WorkPos.x + viewport->WorkSize.x * 0.5f;

    // Toast pill sizing — fit inside status bar with margin
    float pillMarginY = nde("pill-margin-y", 3.0f) * dp;
    float pillHeight = sbHeight - pillMarginY * 2.0f;
    float pillPadX = nde("padding-x", 12.0f) * dp;
    float pillRounding = nde("pill-rounding", 12.0f) * dp;

    // Get accent color based on type — resolved from theme palette
    ImVec4 accent_color, text_color;
    const char* icon = "";

    switch (notif.type) {
        case NotificationType::Success:
            accent_color = ImGui::ColorConvertU32ToFloat4(S.resolveColor("var(--toast-success-accent)", IM_COL32(50, 180, 80, 255)));
            text_color   = ImGui::ColorConvertU32ToFloat4(S.resolveColor("var(--toast-success-text)",   IM_COL32(180, 255, 180, 255)));
            icon = ICON_MD_CHECK_CIRCLE;
            break;
        case NotificationType::Warning:
            accent_color = ImGui::ColorConvertU32ToFloat4(S.resolveColor("var(--toast-warning-accent)", IM_COL32(204, 166, 50, 255)));
            text_color   = ImGui::ColorConvertU32ToFloat4(S.resolveColor("var(--toast-warning-text)",   IM_COL32(255, 230, 130, 255)));
            icon = ICON_MD_WARNING;
            break;
        case NotificationType::Error:
            accent_color = ImGui::ColorConvertU32ToFloat4(S.resolveColor("var(--toast-error-accent)", IM_COL32(204, 64, 64, 255)));
            text_color   = ImGui::ColorConvertU32ToFloat4(S.resolveColor("var(--toast-error-text)",   IM_COL32(255, 153, 153, 255)));
            icon = ICON_MD_ERROR;
            break;
        case NotificationType::Info:
        default:
            accent_color = ImGui::ColorConvertU32ToFloat4(S.resolveColor("var(--toast-info-accent)", IM_COL32(100, 160, 220, 255)));
            text_color   = ImGui::ColorConvertU32ToFloat4(S.resolveColor("var(--toast-info-text)",   IM_COL32(215, 235, 255, 255)));
            icon = ICON_MD_INFO;
            break;
    }

    // Calculate fade based on progress
    float progress = notif.getProgress();
    float alpha = 1.0f;
    if (progress > 0.7f) {
        // Fade out in last 30%
        alpha = (1.0f - progress) / 0.3f;
    }
    
    accent_color.w *= alpha;
    text_color.w *= alpha;

    // Measure text width to auto-size the pill
    ImFont* textFont = material::Type().caption();
    ImFont* iconFont = material::Type().iconSmall();
    float iconW = iconFont ? iconFont->CalcTextSizeA(iconFont->LegacySize, FLT_MAX, 0.0f, icon).x : 0.0f;
    float iconGap = 4.0f * dp;
    float msgW = textFont ? textFont->CalcTextSizeA(textFont->LegacySize, FLT_MAX, 0.0f, notif.message.c_str()).x : 100.0f;
    float pillWidth = pillPadX + iconW + iconGap + msgW + pillPadX;
    // Clamp to reasonable bounds
    float maxPillW = viewport->WorkSize.x * 0.5f;
    if (pillWidth > maxPillW) pillWidth = maxPillW;

    // Position: centered horizontally, inside status bar vertically
    float pillX = viewCenterX - pillWidth * 0.5f;
    float pillY = viewBottom - sbHeight + pillMarginY;

    // Draw directly on foreground draw list (no ImGui window overhead)
    ImDrawList* dl = ImGui::GetForegroundDrawList();
    ImVec2 pMin(pillX, pillY);
    ImVec2 pMax(pillX + pillWidth, pillY + pillHeight);

    // Glass card background — translucent white fill + noise grain + light border
    int glassAlpha = (int)(nde("glass-fill-alpha", 18.0f) * alpha);
    int glassBorderAlpha = (int)(nde("glass-border-alpha", 35.0f) * alpha);
    material::GlassPanelSpec glassSpec;
    glassSpec.rounding    = pillRounding;
    glassSpec.fillAlpha   = glassAlpha;
    glassSpec.borderAlpha = glassBorderAlpha;
    glassSpec.borderWidth = 1.0f;
    material::DrawGlassPanel(dl, pMin, pMax, glassSpec);

    // Colored accent border on top of the glass border for type indication
    ImU32 accentCol = ImGui::ColorConvertFloat4ToU32(accent_color);
    dl->AddRect(pMin, pMax, accentCol, pillRounding, 0, 1.0f);

    // Progress bar at bottom of pill (accent-colored), clipped to pill rounded
    // corners.  Draw a full-pill-size rounded rect and clip it to just the
    // bottom-left progress strip so both bottom corners are respected.
    float progH = nde("progress-bar-height", 2.0f) * dp;
    float progW = pillWidth * (1.0f - progress);
    if (progW > 0.0f) {
        ImVec2 clipMin(pillX, pMax.y - progH);
        ImVec2 clipMax(pillX + progW, pMax.y);
        dl->PushClipRect(clipMin, clipMax, true);
        dl->AddRectFilled(pMin, pMax, accentCol, pillRounding);
        dl->PopClipRect();
    }

    // Icon + text vertically centered
    float contentY = pillY + (pillHeight - (textFont ? textFont->LegacySize : 14.0f)) * 0.5f;
    float cursorX = pillX + pillPadX;

    // Icon (accent colored)
    if (iconFont) {
        float iconY = pillY + (pillHeight - iconFont->LegacySize) * 0.5f;
        dl->AddText(iconFont, iconFont->LegacySize, ImVec2(cursorX, iconY), accentCol, icon);
        cursorX += iconW + iconGap;
    }

    // Message text (clipped to pill bounds)
    if (textFont) {
        ImU32 textCol = ImGui::ColorConvertFloat4ToU32(text_color);
        dl->PushClipRect(ImVec2(cursorX, pillY), ImVec2(pMax.x - pillPadX, pMax.y), true);
        dl->AddText(textFont, textFont->LegacySize, ImVec2(cursorX, contentY), textCol, notif.message.c_str());
        dl->PopClipRect();
    }
}

} // namespace ui
} // namespace dragonx
