#!/usr/bin/env python3
"""
Append an include-tree comment after the contents of each `memmap*.ld` under
`src/*/pico_platform/`.

The comment matches the output of `memmap_include_tree.py` (two columns, no color).
Re-running replaces a previous block marked `BEGIN_MEMMAP_INCLUDE_TREE` /
`END_MEMMAP_INCLUDE_TREE` (at the end of the file, or at the beginning for older runs).

A companion `memmap_xxx.cmake` file is written next to each `memmap_xxx.ld`,
containing `pico_add_link_depend(pico_standard_link ...)` for every transitively
included linker-script fragment of that memmap, with paths expressed as
`${PICO_SDK_PATH}/...` relative to the SDK root.

Examples:

    ./tools/memmap_annotate.py # annotates all memmap*.ld files in the SDK

    ./tools/memmap_annotate.py --ci # does not write files; exits with failure if any memmap would need updating
"""

from __future__ import annotations

import argparse
import re
import sys
from pathlib import Path

_TOOLS = Path(__file__).resolve().parent
if str(_TOOLS) not in sys.path:
    sys.path.insert(0, str(_TOOLS))

import memmap_include_tree as inc_tree

_ANNOT_BEGIN = "/* BEGIN_MEMMAP_INCLUDE_TREE\n"
_ANNOT_END = " * END_MEMMAP_INCLUDE_TREE */\n"
_ANNOT_BLOCK_CORE = (
    r"/\* BEGIN_MEMMAP_INCLUDE_TREE\n.*?\n \* END_MEMMAP_INCLUDE_TREE \*/\s*"
)


def strip_annotation_block(text: str) -> str:
    """Remove a previously inserted annotation block (trailing, or legacy leading)."""
    t = text
    # Preferred: block at end of file
    m = re.search(_ANNOT_BLOCK_CORE + r"\Z", t, re.DOTALL)
    if m:
        head = t[: m.start()].rstrip("\n")
        if head:
            head += "\n"
        return head
    # Legacy: block was prepended at the beginning
    m2 = re.match(_ANNOT_BLOCK_CORE + r"\n?", t, re.DOTALL)
    if m2:
        return t[m2.end() :].lstrip("\n")
    return t


def build_annotation_block(tree_lines: list[str]) -> str:
    parts = [
        _ANNOT_BEGIN,
        " * This is the default include tree for this file (generated by tools/memmap_annotate.py\n"
        " * and tools/memmap_include_tree.py). To override any files in this tree, see the\n"
        " * pico_add_linker_script_override_path CMake function under pico_standard_link.\n",
        " *\n",
    ]
    for ln in tree_lines:
        parts.append(" * " + ln + "\n")
    parts.append(_ANNOT_END)
    return "".join(parts)


def collect_included_files(nodes: list[inc_tree.ChildRow], acc: set[Path] | None = None) -> set[Path]:
    """Recursively collect all resolved file paths from an include tree (excludes the root)."""
    if acc is None:
        acc = set()
    for path, subs, _ in nodes:
        if path.exists():
            acc.add(path)
        collect_included_files(subs, acc)
    return acc


def build_cmake_block(included_files: set[Path], sdk_root: Path, memmap_stem: str) -> str:
    func_name = "pico_add_memmap_link_depends_internal"
    lines = [
        "# Auto-generated by tools/memmap_annotate.py — do not edit by hand\n",
        f"function({func_name} TARGET)\n",
    ]
    for p in sorted(included_files):
        try:
            rel = p.relative_to(sdk_root)
        except ValueError:
            rel = p
        lines.append(
            f"    pico_add_link_depend(${{TARGET}} ${{PICO_SDK_PATH}}/{rel.as_posix()})\n"
        )
    lines.append("endfunction()\n")
    return "".join(lines)


def annotate_one(
    path: Path,
    sdk_root: Path,
    platform: str | None,
    *,
    ci: bool,
) -> tuple[bool, str]:
    """Return (ok, status message). ok is False on unresolved includes."""
    path = path.resolve()
    search_dirs = inc_tree.default_search_dirs(sdk_root, path, platform)
    visited: set[Path] = set()
    user_l_set: frozenset[Path] = frozenset()
    user_l_labels: dict[Path, str] = {}
    root_node, root_children = inc_tree.walk_includes(
        path, search_dirs, user_l_set, user_l_labels, visited
    )
    missing = inc_tree.collect_unresolved_include_paths(root_children)
    if missing:
        names = ", ".join(m.name for m in missing)
        return False, f"unresolved INCLUDE: {names}"

    included_files = collect_included_files(root_children)

    lines = inc_tree.format_tree_lines(root_node, root_children, color=False)
    block = build_annotation_block(lines)
    old_ld = path.read_text(encoding="utf-8", errors="replace")
    body = strip_annotation_block(old_ld)
    if body and not body.endswith("\n"):
        body += "\n"
    new_ld = body + "\n" + block if body else block

    cmake_path = path.with_suffix(".cmake")
    new_cmake = build_cmake_block(included_files, sdk_root, path.stem)
    old_cmake = cmake_path.read_text(encoding="utf-8", errors="replace") if cmake_path.exists() else ""

    if new_ld == old_ld and new_cmake == old_cmake:
        return True, "unchanged"
    if ci:
        return True, "needs updating"
    if new_ld != old_ld:
        path.write_text(new_ld, encoding="utf-8")
    if new_cmake != old_cmake:
        cmake_path.write_text(new_cmake, encoding="utf-8")
    return True, "updated"


def parse_args(argv: list[str]) -> argparse.Namespace:
    p = argparse.ArgumentParser(
        description=inc_tree.fold_docstring_for_argparse(__doc__ or ""),
        formatter_class=argparse.RawDescriptionHelpFormatter,
    )
    p.add_argument(
        "--sdk-root",
        type=Path,
        default=None,
        help=inc_tree.CLI_HELP_SDK_ROOT,
    )
    p.add_argument(
        "--platform",
        default=None,
        metavar="CHIP",
        help=inc_tree.CLI_HELP_PLATFORM,
    )
    p.add_argument(
        "--ci",
        action="store_true",
        help="Do not write files; exit with failure if any memmap would need updating",
    )
    p.add_argument(
        "paths",
        nargs="*",
        type=Path,
        metavar="MEMMAP.LD",
        help="Linker scripts to annotate (default: all src/*/pico_platform/memmap*.ld)",
    )
    return p.parse_args(argv)


def main(argv: list[str]) -> int:
    args = parse_args(argv)
    sdk_root = args.sdk_root
    if args.paths:
        files = [p.resolve() for p in args.paths]
        for f in files:
            if not f.is_file():
                print(f"error: not a file: {f}", file=sys.stderr)
                return 1
        if sdk_root is None:
            sdk_root = inc_tree.infer_sdk_root(files[0])
        if sdk_root is None:
            print(inc_tree.CLI_MSG_SDK_ROOT_INFER_FAILED, file=sys.stderr)
            return 1
    else:
        if sdk_root is None:
            sdk_root = inc_tree.infer_sdk_root(Path.cwd())
        if sdk_root is None:
            print(inc_tree.CLI_MSG_SDK_ROOT_INFER_FAILED, file=sys.stderr)
            return 1
        files = sorted(sdk_root.glob("src/*/pico_platform/memmap*.ld"))

    if not files:
        print("error: no memmap*.ld files to process", file=sys.stderr)
        return 1

    sdk_root = sdk_root.resolve()
    if args.platform is not None:
        perr = inc_tree.validate_explicit_platform(sdk_root, args.platform)
        if perr:
            print(f"error: {perr}", file=sys.stderr)
            return 1

    err = 0
    for f in files:
        plat = args.platform or inc_tree.infer_platform_chip(f)
        ok, msg = annotate_one(f, sdk_root, plat, ci=args.ci)
        try:
            tag = str(f.relative_to(sdk_root))
        except ValueError:
            tag = str(f)
        if ok:
            print(inc_tree.format_memmap_annotate_status_line(tag, msg))
            if args.ci and msg == "needs updating":
                err = 1
        else:
            print(f"{tag}: {msg}", file=sys.stderr)
            err = 1
    return err


if __name__ == "__main__":
    raise SystemExit(main(sys.argv[1:]))
