using AlienAttack.MonoGame.GameLoops;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System;

namespace AlienAttack.MonoGame.Hud;

public record DrawHudContext : DrawContext
{
    public int Health;
    public int Shield;
}

public class Hud
{
    private Texture2D _pixel;

    public Hud(Game game)
    {
        _pixel = new Texture2D(game.GraphicsDevice, 1, 1);
        _pixel.SetData(new[] { Color.White });
    }

    public void Draw(DrawHudContext context)
    {
        DrawSideBars(context);
    }

    private void DrawSideBars(DrawHudContext context)
    {
        SpriteBatch sb = context.SpriteBatch;

        int screenW = context.ViewTransoform.ScreenWidth;
        int screenH = context.ViewTransoform.ScreenHeight;

        double totalSeconds = context.GameTime.TotalGameTime.TotalSeconds;

        int health = Math.Clamp(context.Health, 0, 100);
        int shield = Math.Clamp(context.Shield, 0, 100);

        int marginTop = 10;
        int marginBottom = 10;

        int segments = 100;
        int gap = 4;

        int barWidth = 10;        // thickness of the colored segments
        int borderPad = 2;       // thickness around the bar (border area)
        int borderW = barWidth + borderPad * 2;

        int barHeight = screenH - marginTop - marginBottom;
        int segHeight = Math.Max(1, (barHeight - gap * (segments - 1)) / segments);
        int usedHeight = segments * segHeight + (segments - 1) * gap;

        int barTopY = marginTop;
        int barBottomY = marginTop + usedHeight;

        // Put left / right bars near screen edges
        int leftBorderX = 8;
        int rightBorderX = screenW - 8 - borderW;

        // Colors (tweak as desired)
        Color healthOn = new Color(255, 140, 0);   // orange
        Color shieldOn = new Color(60, 140, 255);  // blue

        Color off = new Color(28, 28, 28);         // empty segment base

        // Draw metallic frames (behind segments)
        //DrawMetallicFrame(sb, new Rectangle(leftBorderX, barTopY - borderPad, borderW, usedHeight + borderPad * 2));
        //DrawMetallicFrame(sb, new Rectangle(rightBorderX, barTopY - borderPad, borderW, usedHeight + borderPad * 2));

        // Segment drawing X starts inside the border
        int leftSegX = leftBorderX + borderPad;
        int rightSegX = rightBorderX + borderPad;

        // Low health pulse settings
        bool lowHealth = health <= 20;
        float pulse = lowHealth
            ? (0.85f + 0.15f * (float)Math.Sin(totalSeconds * 6.0)) // subtle wobble
            : 1f;

        DrawSegmentedBar(
            sb, leftSegX, barBottomY, barWidth, segHeight, gap,
            value0To100: health,
            onColor: healthOn,
            offColor: off,
            segments: segments,
            // pulse only on filled health segments
            pulseMultiplier: pulse,
            pulseFilledOnly: true
        );

        DrawSegmentedBar(
            sb, rightSegX, barBottomY, barWidth, segHeight, gap,
            value0To100: shield,
            onColor: shieldOn,
            offColor: off,
            segments: segments,
            // no pulse for shield by default
            pulseMultiplier: 1f,
            pulseFilledOnly: true
        );
    }

    private void DrawSegmentedBar(
    SpriteBatch sb,
    int x,
    int bottomY,
    int barWidth,
    int segHeight,
    int gap,
    int value0To100,
    Color onColor,
    Color offColor,
    int segments,
    float pulseMultiplier,
    bool pulseFilledOnly)
    {
        // Gradient: bottom darker, top brighter
        float minBrightness = 0.55f;
        float maxBrightness = 1.00f;

        for (int i = 0; i < segments; i++)
        {
            int y = bottomY - (i + 1) * segHeight - i * gap;

            // i=0 bottom, i=segments-1 top
            float t = i / (float)(segments - 1);
            float brightness = MathHelper.Lerp(minBrightness, maxBrightness, t);

            bool filled = i < value0To100;
            Color baseColor = filled ? onColor : offColor;

            // Apply pulse (usually only on the filled parts)
            if (pulseMultiplier != 1f && (!pulseFilledOnly || filled))
            {
                brightness *= pulseMultiplier;
                brightness = Math.Min(brightness, 1.2f); // allow a tiny “pop”, still safe
            }

            Color finalColor = ScaleRgb(baseColor, brightness);
            sb.Draw(_pixel, new Rectangle(x, y, barWidth, segHeight), finalColor);

            // Optional: little “shine” line on filled segments (adds a nice DOS UI feel)
            // Draw a 1px highlight on the left edge of lit segments.
            if (filled && barWidth >= 3)
            {
                var shine = ScaleRgb(Color.White, 0.10f * brightness);
                sb.Draw(_pixel, new Rectangle(x, y, 1, segHeight), shine);
            }
        }
    }

    private static Color ScaleRgb(Color c, float mul)
    {
        mul = Math.Max(0f, mul);
        byte r = (byte)Math.Clamp((int)(c.R * mul), 0, 255);
        byte g = (byte)Math.Clamp((int)(c.G * mul), 0, 255);
        byte b = (byte)Math.Clamp((int)(c.B * mul), 0, 255);
        return new Color(r, g, b, c.A);
    }

    private void DrawMetallicFrame(SpriteBatch sb, Rectangle outer)
    {
        // “Metal” palette
        Color outerBorder = new Color(10, 10, 10);
        Color fill = new Color(45, 45, 45);

        Color highlight = new Color(90, 90, 90); // top/left
        Color shadow = new Color(20, 20, 20);    // bottom/right

        // Outer border
        sb.Draw(_pixel, outer, outerBorder);

        // Inner fill
        var inner = new Rectangle(outer.X + 1, outer.Y + 1, outer.Width - 2, outer.Height - 2);
        if (inner.Width > 0 && inner.Height > 0)
            sb.Draw(_pixel, inner, fill);

        // Bevel lines (1px)
        // Top highlight
        sb.Draw(_pixel, new Rectangle(inner.X, inner.Y, inner.Width, 1), highlight);
        // Left highlight
        sb.Draw(_pixel, new Rectangle(inner.X, inner.Y, 1, inner.Height), highlight);

        // Bottom shadow
        sb.Draw(_pixel, new Rectangle(inner.X, inner.Bottom - 1, inner.Width, 1), shadow);
        // Right shadow
        sb.Draw(_pixel, new Rectangle(inner.Right - 1, inner.Y, 1, inner.Height), shadow);

        // Optional: an even tighter inner “lip” for extra metal feel
        var lip = new Rectangle(inner.X + 1, inner.Y + 1, inner.Width - 2, inner.Height - 2);
        if (lip.Width > 0 && lip.Height > 0)
        {
            Color lipDark = new Color(35, 35, 35);
            sb.Draw(_pixel, lip, lipDark);
        }
    }
}