#!/usr/bin/env python3
"""
Generate src/logos_data.inc from the ANSI art files under logos/.

Each ANSI logo is converted into a NULL-terminated array of C string literals
so render.c can embed them directly without needing to parse files at runtime.
"""

from __future__ import annotations

import argparse
from pathlib import Path

LOGO_SOURCES = [
    ("logo_86_dos", "logos/86.ans"),
    ("logo_concurrentdos", "logos/concurrentdos.ans"),
    ("logo_dos", "logos/dos.ans"),
    ("logo_dosbian", "logos/dosbian.ans"),
    ("logo_dosbox", "logos/dosbox.ans"),
    ("logo_dosbox_staging", "logos/dosbox_staging.ans"),
    ("logo_dosbox_x", "logos/dosbox_x.ans"),
    ("logo_dr_dos", "logos/drdos.ans"),
    ("logo_freedos", "logos/freedos.ans"),
    ("logo_ms_dos", "logos/msdos.ans"),
    ("logo_novell_dos", "logos/novell.ans"),
    ("logo_pc_dos", "logos/ibmdos.ans"),
]


def split_lines(path: Path) -> list[bytes]:
    """Return the ANSI file as a list of raw lines without line endings."""
    data = path.read_bytes()
    # splitlines() handles CRLF/CR/LF and preserves empty lines.
    return data.splitlines()


def to_c_literal(line: bytes) -> str:
    """Convert a raw line to a C string literal with escaped bytes."""
    pieces = ['"']
    for byte in line:
        if byte == 0x5C:  # backslash
            pieces.append("\\\\")
        elif byte == 0x22:  # double quote
            pieces.append('\\"')
        elif byte == 0x07:
            pieces.append("\\a")
        elif byte == 0x08:
            pieces.append("\\b")
        elif byte == 0x09:
            pieces.append("\\t")
        elif byte == 0x0C:
            pieces.append("\\f")
        elif byte == 0x0B:
            pieces.append("\\v")
        elif 0x20 <= byte <= 0x7E:
            pieces.append(chr(byte))
        else:
            pieces.append(f"\\x{byte:02x}")
    pieces.append('"')
    return "".join(pieces)


def generate(output: Path) -> None:
    root = Path(__file__).resolve().parents[1]
    lines = [
        "/* Auto-generated by tools/generate_logos_data.py. Do not edit. */",
        "",
    ]

    for symbol, rel_path in LOGO_SOURCES:
        logo_path = root / rel_path
        if not logo_path.exists():
            raise FileNotFoundError(f"Missing logo file: {logo_path}")
        lines.append(f"static const char *const {symbol}[] = {{")
        for raw_line in split_lines(logo_path):
            lines.append(f"    {to_c_literal(raw_line)},")
        lines.append("    NULL,")
        lines.append("};")
        lines.append("")

    output_path = root / output
    output_path.write_text("\n".join(lines), encoding="utf-8")


def main() -> None:
    parser = argparse.ArgumentParser(description=__doc__)
    parser.add_argument(
        "-o",
        "--output",
        default="src/logos_data.inc",
        type=Path,
        help="Path to write the generated include (default: %(default)s)",
    )
    args = parser.parse_args()
    generate(args.output)


if __name__ == "__main__":
    main()
