"""Generate SVG images for README usage snippets.

Produces files in ``images/usage`` for commonly documented features,
including styling, underline modes, rainbow, gradients, and ArtRegistry usage.

Requires Consolas fonts installed at the standard Windows location.
"""

import os
import sys

sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "src"))

from fontTools.ttLib import TTFont  # type: ignore

from pyansistring import (
    ANSIString,
    ArtRegistry,
    ColorGeneratorContext,
    register_color_generator,
    unregister_color_generator,
)
from pyansistring.constants import SGR, Background, Foreground, UnderlineMode

# ── Font paths (Consolas family, standard Windows location) ────────────────
FONT_DIR = "C:\\Windows\\Fonts"
FONT_REG = os.path.join(FONT_DIR, "consola.ttf")
FONT_BOLD = os.path.join(FONT_DIR, "consolab.ttf")
FONT_ITAL = os.path.join(FONT_DIR, "consolai.ttf")
FONT_BI = os.path.join(FONT_DIR, "consolaz.ttf")
FONT_PX = 16

for fpath in (FONT_REG, FONT_BOLD, FONT_ITAL, FONT_BI):
    if not os.path.exists(fpath):
        sys.exit(f"Font not found: {fpath}")

reg = TTFont(FONT_REG)
bold = TTFont(FONT_BOLD)
ital = TTFont(FONT_ITAL)
bi = TTFont(FONT_BI)
examples: dict[str, ANSIString] = {}

OUT = os.path.join(os.path.dirname(__file__), "..", "images", "usage")
os.makedirs(OUT, exist_ok=True)


def write(name: str, svg: str) -> None:
    path = os.path.join(OUT, name)
    with open(path, "w", encoding="utf-8") as f:
        f.write(svg)
    print(f"  {name}")


def add(name: str, s: ANSIString):
    examples[name] = s


def zigzag_generator(context: ColorGeneratorContext) -> list[tuple[int, int, int]]:
    """Return a mirrored zigzag palette sized to the requested step count."""
    palette = [
        (84, 161, 255),
        (255, 99, 71),
        (255, 215, 0),
        (120, 220, 160),
    ]
    out: list[tuple[int, int, int]] = []
    for index in range(max(2, context["step_count"])):
        phase = (index // len(palette)) % 2
        slot = index % len(palette)
        out.append(palette[slot] if phase == 0 else palette[-slot - 1])
    return out


# ── Unstyled text ─────────────────────────────────────────────────────────
add("unstyled.svg", ANSIString("Hello, World!"))

# ── Styling the whole string ──────────────────────────────────────────────
add(
    "whole.svg",
    ANSIString("Hello, World!")
    .fg_4b(Foreground.YELLOW)
    .bg_4b(Background.BLUE)
    .style(SGR.BOLD),
)

# ── Styling by index slice ────────────────────────────────────────────────
add(
    "slice.svg",
    ANSIString("Hello, World!")
    .fg_4b(Foreground.YELLOW, (0, 5), (7, 12))  # "Hello" and "World"
    .bg_4b(Background.BLUE, (7, 12))  # "World"
    .style(SGR.BOLD, (7, 12)),  # "World"
)

# ── Styling by word ───────────────────────────────────────────────────────
add(
    "words.svg",
    ANSIString("Hello, World!")
    .fg_4b_words(Foreground.YELLOW, "Hello", "World")
    .bg_4b_words(Background.BLUE, "World")
    .style_words(SGR.BOLD, "Hello", "World"),
)

# ── SGR formatting (bold + underline) ─────────────────────────────────────
add(
    "sgr.svg",
    ANSIString("Hello, World!").style(SGR.BOLD).style(SGR.UNDERLINE),
)

# ── 4-bit colour ──────────────────────────────────────────────────────────
add(
    "4bit.svg",
    ANSIString("Hello, World!").fg_4b(Foreground.YELLOW).bg_4b(Background.BLUE),
)

# ── 8-bit colour ──────────────────────────────────────────────────────────
add(
    "8bit.svg",
    ANSIString("Hello, World!")
    .fg_8b(11)  # Bright Yellow
    .bg_8b(4)  # Blue
    .ul_8b(74),  # Muted Sky Blue
)

# ── 24-bit (true colour) ──────────────────────────────────────────────────
add(
    "rgb.svg",
    ANSIString("Hello, World!")
    .fg_24b(255, 255, 0)  # Bright Yellow
    .bg_24b(0, 0, 238)  # Blue
    .ul_24b(135, 175, 215),  # Light Steel Blue
)

# ── Underline modes ───────────────────────────────────────────────────────
add(
    "underline.svg",
    ANSIString("Hello, World!")
    .bg_24b(255, 255, 255)  # White
    .ul_24b(255, 0, 0)  # Red
    .style(UnderlineMode.DOUBLE),
)

# ── Rainbow ───────────────────────────────────────────────────────────────
add(
    "rainbow.svg",
    ANSIString("Hello, World! This is rainbow text!").rainbow(fg=True),
)

# ── Gradient (string-wide) ───────────────────────────────────────────────
add(
    "gradient.svg",
    ANSIString("Hello, World! This is gradient text!").gradient(
        [(84, 161, 255), (233, 200, 216)],
        fg=True,
    ),
)

# ── Gradient by words ─────────────────────────────────────────────────────
add(
    "gradient_words.svg",
    ANSIString("Hello, colorful gradient world!").gradient_words(
        [(255, 99, 71), (255, 215, 0)],
        "Hello",
        "world",
        case_sensitive=False,
        fg=True,
    ),
)

# ── Gradient by coordinates ───────────────────────────────────────────────
add(
    "gradient_coordinates.svg",
    ANSIString("HELLO\nworld").gradient_coordinates(
        [(255, 0, 120), (0, 200, 255)],
        (1, 1),
        (2, 1),
        (3, 1),
        (4, 1),
        (5, 1),
        index_base=1,
        fg=True,
    ),
)

# ── ArtRegistry (custom generator) ───────────────────────────────────────
register_color_generator("zigzag_usage_v1", zigzag_generator)
try:
    custom_registry = ArtRegistry()
    custom_registry.register(
        "ZIGZAG",
        " /\\/\\/\\/\\\n \\/\\/\\/\\/",
        colorings=(
            {
                "mode": "gradient",
                "colors": {
                    "generator": "zigzag_usage_v1",
                    "mode": "seeded",
                    "seed": 42,
                },
                "skip_whitespace": True,
                "fg": True,
            },
        ),
    )
    add("art_registry_zigzag.svg", custom_registry.get_colored_art("ZIGZAG"))
finally:
    unregister_color_generator("zigzag_usage_v1")


# ── Generate all SVGs ─────────────────────────────────────────────────────
print(f"Generating {len(examples)} SVG examples in {OUT}:")

for filename, ansistr in examples.items():
    svg = ansistr.to_svg(
        reg,
        font_size_px=FONT_PX,
        font_bold=bold,
        font_italic=ital,
        font_bold_italic=bi,
        convert_text_to_path=True,
    )
    write(filename, svg)

print(f"\nDone — {len(examples)} files written.")
