namespace HellionChat.Themes;

// Per-slot ABGR byte-lerp between two ThemeAbgrCache value-records.
// Pattern anchor: imgui.cpp:2820-2828 ImAlphaBlendColors -- decompose
// each byte, lerp via Math.Round, recompose. Stack-allocated output
// (readonly record struct), no heap pressure inside the crossfade
// window. t is clamped to [0, 1] so float drift cannot overshoot.
internal static class ThemeAbgrCacheLerp
{
    public static ThemeAbgrCache Lerp(ThemeAbgrCache from, ThemeAbgrCache to, float t)
    {
        t = Math.Clamp(t, 0f, 1f);

        return new ThemeAbgrCache(
            PrimaryDark: LerpAbgr(from.PrimaryDark, to.PrimaryDark, t),
            Primary: LerpAbgr(from.Primary, to.Primary, t),
            PrimaryLight: LerpAbgr(from.PrimaryLight, to.PrimaryLight, t),
            PrimaryGlow: LerpAbgr(from.PrimaryGlow, to.PrimaryGlow, t),
            AccentDark: LerpAbgr(from.AccentDark, to.AccentDark, t),
            Accent: LerpAbgr(from.Accent, to.Accent, t),
            AccentLight: LerpAbgr(from.AccentLight, to.AccentLight, t),
            Identity: LerpAbgr(from.Identity, to.Identity, t),
            WindowBg: LerpAbgr(from.WindowBg, to.WindowBg, t),
            ChildBg: LerpAbgr(from.ChildBg, to.ChildBg, t),
            FrameBg: LerpAbgr(from.FrameBg, to.FrameBg, t),
            Surface: LerpAbgr(from.Surface, to.Surface, t),
            SurfaceHover: LerpAbgr(from.SurfaceHover, to.SurfaceHover, t),
            Border: LerpAbgr(from.Border, to.Border, t),
            TextPrimary: LerpAbgr(from.TextPrimary, to.TextPrimary, t),
            TextMuted: LerpAbgr(from.TextMuted, to.TextMuted, t),
            TextDim: LerpAbgr(from.TextDim, to.TextDim, t),
            StatusSuccess: LerpAbgr(from.StatusSuccess, to.StatusSuccess, t),
            StatusDanger: LerpAbgr(from.StatusDanger, to.StatusDanger, t),
            StatusWarning: LerpAbgr(from.StatusWarning, to.StatusWarning, t),
            StatusInfo: LerpAbgr(from.StatusInfo, to.StatusInfo, t)
        );
    }

    private static uint LerpAbgr(uint from, uint to, float t)
    {
        var ra = (byte)(from & 0xFFu);
        var ga = (byte)((from >> 8) & 0xFFu);
        var ba = (byte)((from >> 16) & 0xFFu);
        var aa = (byte)((from >> 24) & 0xFFu);

        var rb = (byte)(to & 0xFFu);
        var gb = (byte)((to >> 8) & 0xFFu);
        var bb = (byte)((to >> 16) & 0xFFu);
        var ab = (byte)((to >> 24) & 0xFFu);

        // Math.Round (default ToEven) matches ColourUtil.ApplyAlpha so a
        // crossfade-into-hover transition does not produce a one-byte
        // jump at the midpoint between the two paths.
        var r = (byte)Math.Round(ra + (rb - ra) * t);
        var g = (byte)Math.Round(ga + (gb - ga) * t);
        var b = (byte)Math.Round(ba + (bb - ba) * t);
        var a = (byte)Math.Round(aa + (ab - aa) * t);

        return ((uint)a << 24) | ((uint)b << 16) | ((uint)g << 8) | r;
    }
}
