#!/usr/bin/python
# generate_braille_table_names.py
#
# Generate brltablenames.py from liblouis table metadata.
# Run this whenever the liblouis tables are updated to refresh
# the set of available table names for translation.
#
# Copyright 2026 Igalia, S.L.
# Author: Joanmarie Diggs <jdiggs@igalia.com>
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
# Boston MA  02110-1301 USA.

"""Generate brltablenames.py from liblouis table metadata.

Parses metadata comments from each .ctb and .utb file in a liblouis tables directory.
Uses #-index-name as the display name, falling back to #-display-name, then metadata
from a .tbl wrapper that includes the table, then the filename stem.

Usage:
    python tools/generate_braille_table_names.py /path/to/liblouis/tables
"""

import argparse
import re
import sys
from pathlib import Path

_TABLE_EXTENSIONS = {".ctb", ".utb"}
_INDEX_NAME_RE = re.compile(r"^#-index-name:\s*(.+)$")
_DISPLAY_NAME_RE = re.compile(r"^#-display-name:\s*(.+)$")
_INCLUDE_RE = re.compile(r"^include\s+(\S+)")

_FILE_HEADER = '''\
# Orca
#
# Copyright 2004-2009 Sun Microsystems Inc.
# Copyright 2026 Igalia, S.L.
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
# Boston MA  02110-1301 USA.

# This file is auto-generated by tools/generate_braille_table_names.py.
# Do not edit manually. Re-run the tool after updating liblouis.

# pylint: disable=too-many-lines

"""Braille translation table names for localization.

These are in their own module so that we can present them in the correct
language when users change the synthesizer language on the fly without
having to reload a bunch of modules."""

from .orca_i18n import _  # pylint: disable=import-error
'''

_TRANSLATOR_COMMENT = (
    "# Translators: This is the name of a braille translation table\n"
    "    # provided by liblouis (https://liblouis.io). Many of the terms\n"
    "    # used in these names (e.g. contracted, uncontracted, grade,\n"
    "    # computer braille) are explained at\n"
    "    # https://en.wikipedia.org/wiki/Braille."
)


def _get_table_name(table_path):
    """Extract the best available name from a table file's header."""

    index_name = None
    display_name = None
    try:
        with open(table_path, encoding="utf-8", errors="replace") as f:
            for line in f:
                if not line.startswith("#"):
                    if line.strip():
                        break
                    continue
                if match := _INDEX_NAME_RE.match(line):
                    index_name = match.group(1).strip()
                elif match := _DISPLAY_NAME_RE.match(line):
                    display_name = match.group(1).strip()
    except OSError:
        pass
    return index_name or display_name or table_path.stem


def _build_tbl_name_map(tables_path):
    """Build a mapping from included .ctb/.utb filenames to .tbl metadata names."""

    name_map = {}
    for tbl_file in tables_path.glob("*.tbl"):
        name = _get_table_name(tbl_file)
        if name == tbl_file.stem:
            continue
        try:
            with open(tbl_file, encoding="utf-8", errors="replace") as f:
                for line in f:
                    if match := _INCLUDE_RE.match(line):
                        included = match.group(1)
                        if Path(included).suffix in _TABLE_EXTENSIONS:
                            name_map[included] = name
        except OSError:
            pass
    return name_map


def _get_table_entries(tables_dir):
    """Scan tables_dir for table files and extract their names."""

    tables_path = Path(tables_dir)
    tbl_names = _build_tbl_name_map(tables_path)
    entries = []
    for table_file in sorted(tables_path.iterdir(), key=lambda p: p.name.lower()):
        if table_file.suffix not in _TABLE_EXTENSIONS:
            continue
        name = _get_table_name(table_file)
        if name == table_file.stem:
            name = tbl_names.get(table_file.name, name)
        entries.append((table_file.name, name))

    return entries


def _escape_for_python_string(text):
    """Escape characters that would break a double-quoted Python string."""

    return text.replace("\\", "\\\\").replace('"', '\\"')


def _generate_module(entries):
    """Generate the brltablenames.py content."""

    lines = [_FILE_HEADER, "TABLE_NAMES: dict[str, str] = {"]
    for filename, display_name in entries:
        escaped = _escape_for_python_string(display_name)
        lines.append(f"    {_TRANSLATOR_COMMENT}")
        lines.append(f'    "{filename}": _("{escaped}"),')
    lines.append("}")
    lines.append("")
    return "\n".join(lines)


def main():
    """Performs the table-name generation."""

    output_path = Path(__file__).resolve().parent.parent / "src" / "orca" / "brltablenames.py"

    parser = argparse.ArgumentParser(
        description="Generate brltablenames.py from liblouis table metadata."
    )
    parser.add_argument(
        "tables_dir",
        type=Path,
        help="Path to the liblouis tables directory.",
    )
    args = parser.parse_args()

    if not args.tables_dir.is_dir():
        print(f"Error: {args.tables_dir} is not a directory.", file=sys.stderr)
        sys.exit(1)

    entries = _get_table_entries(args.tables_dir)
    if not entries:
        print(f"Error: No table files found in {args.tables_dir}.", file=sys.stderr)
        sys.exit(1)

    content = _generate_module(entries)
    output_path.write_text(content, encoding="utf-8")
    print(f"Wrote {len(entries)} table names to {output_path}")


if __name__ == "__main__":
    main()
