using FontStashSharp;
using Microsoft.Xna.Framework.Graphics;

namespace Theriapolis.Game.CodexUI.Core;

/// <summary>
/// Static font registry for CodexUI. Loaded once at game startup via
/// <see cref="LoadAll"/>; widgets read from these fields. The slots map to
/// the design's typographic ladder:
///   - DisplayLarge / Medium / Small  → Cinzel-Bold (fallback: Georgia Bold) — all-caps headings
///   - SerifBody / SerifItalic        → Cormorant Garamond (fallback: Georgia / Georgia Italic)
///   - MonoTag / MonoTagSmall         → JetBrains Mono (fallback: Consolas)
///
/// FontStashSharp loads TTF files into a runtime atlas. We try
/// <c>Content/Fonts/</c> first (project-supplied fonts), then fall back to
/// Windows system fonts so the game runs without bundling Cinzel/Cormorant.
/// </summary>
public static class CodexFonts
{
    public static SpriteFontBase DisplayLarge   = null!;  // ~32 px, codex header
    public static SpriteFontBase DisplayMedium  = null!;  // ~22 px, h2
    public static SpriteFontBase DisplaySmall   = null!;  // ~16 px, h3
    public static SpriteFontBase SerifBody      = null!;  // ~16 px, body text
    public static SpriteFontBase SerifItalic    = null!;  // ~14 px, italic body / trait names
    public static SpriteFontBase MonoTag        = null!;  // ~10 px, eyebrow + tag text
    public static SpriteFontBase MonoTagSmall   = null!;  // ~9 px, sub-tags

    private static FontSystem? _serif;
    private static FontSystem? _italic;
    private static FontSystem? _mono;

    /// <summary>
    /// Load every font slot. Throws on failure — fonts are required for the
    /// codex screen to render anything legible.
    /// </summary>
    public static void LoadAll(GraphicsDevice gd, string contentRoot)
    {
        _serif  = LoadFontSystem(contentRoot, new[] { "Fonts/Cinzel-Bold.ttf", "Fonts/CormorantGaramond-Bold.ttf" },
                                                 new[] { @"C:\Windows\Fonts\georgiab.ttf", @"C:\Windows\Fonts\timesbd.ttf" });
        _italic = LoadFontSystem(contentRoot, new[] { "Fonts/CormorantGaramond-Italic.ttf", "Fonts/CormorantGaramond-Regular.ttf" },
                                                 new[] { @"C:\Windows\Fonts\georgiai.ttf", @"C:\Windows\Fonts\timesi.ttf", @"C:\Windows\Fonts\georgia.ttf" });
        _mono   = LoadFontSystem(contentRoot, new[] { "Fonts/JetBrainsMono-Medium.ttf" },
                                                 new[] { @"C:\Windows\Fonts\consola.ttf", @"C:\Windows\Fonts\consolab.ttf", @"C:\Windows\Fonts\cour.ttf" });

        DisplayLarge  = _serif.GetFont(32f);
        DisplayMedium = _serif.GetFont(22f);
        DisplaySmall  = _serif.GetFont(16f);
        SerifBody     = _italic.GetFont(15f);
        SerifItalic   = _italic.GetFont(14f);
        MonoTag       = _mono.GetFont(11f);
        MonoTagSmall  = _mono.GetFont(9f);
    }

    private static FontSystem LoadFontSystem(string contentRoot, string[] preferred, string[] fallbacks)
    {
        var fs = new FontSystem();
        // Try project-supplied fonts first (Content/Fonts/*).
        foreach (var rel in preferred)
        {
            string path = System.IO.Path.Combine(contentRoot, rel);
            if (System.IO.File.Exists(path))
            {
                fs.AddFont(System.IO.File.ReadAllBytes(path));
                return fs;
            }
        }
        // Fall back to a system font — guaranteed available on the target
        // platforms (Windows Georgia/Times/Consolas; future: macOS / Linux
        // would need their own fallback list).
        foreach (var path in fallbacks)
        {
            if (System.IO.File.Exists(path))
            {
                fs.AddFont(System.IO.File.ReadAllBytes(path));
                return fs;
            }
        }
        throw new System.IO.FileNotFoundException(
            "CodexFonts: no font found in either project Content/Fonts/ or system fallback locations. " +
            $"Preferred: {string.Join(", ", preferred)}; fallbacks: {string.Join(", ", fallbacks)}");
    }
}
