#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-3.0-or-later
"""Maintain independently buildable Debian source packages for Plasma Next."""

import argparse
import sys
from contextlib import nullcontext
from pathlib import Path

sys.path.insert(0, str(Path(__file__).resolve().parent / "lib"))
import project as p  # noqa: E402 - Load tools/lib after configuring its import path.

parser = argparse.ArgumentParser(description=__doc__)
commands = parser.add_subparsers(dest="command", required=True)
for name in ["list", "fetch", "prepare", "check", "build", "clean"]:
    q = commands.add_parser(name)
    q.add_argument("packages", nargs="*")
    q.add_argument("--all", action="store_true")
    q.add_argument("--with-deps", action="store_true")
    if name in ["fetch", "prepare", "build"]:
        q.add_argument("--offline", action="store_true")
    if name == "build":
        q.add_argument(
            "-j",
            "--jobs",
            type=int,
            metavar="N",
            help="Parallel build jobs, defaults to config/release.json",
        )
        q.add_argument(
            "--no-apt-cache",
            action="store_true",
            help="Download build dependencies directly without apt-cacher-ng",
        )
    if name == "clean":
        q.add_argument(
            "--accepted",
            action="store_true",
            help="Also remove accepted artifacts, build records and local repository entries",
        )
    if name == "check":
        q.add_argument("--baseline", action="store_true")
commands.add_parser("clean-apt-cache", help="Remove cached Debian package downloads")
commands.add_parser("audit")
q = commands.add_parser("setup")
q.add_argument(
    "--no-apt-cache",
    action="store_true",
    help="Disable APT caching for this environment",
)
commands.add_parser(
    "reset-environment",
    help="Remove the controller, base image, temporary roots and staged tools",
)
q = commands.add_parser("export")
q.add_argument("--output", type=Path, required=True)
q.add_argument("--signing-home", type=Path)
q.add_argument("--key")
a = parser.parse_args()
if a.command == "build" and a.jobs is not None and a.jobs < 1:
    parser.error("--jobs must be a positive integer")
try:
    if a.command == "clean-apt-cache":
        from cleanup import clean_apt_cache

        with p.lock():
            clean_apt_cache()
        raise SystemExit()
    if a.command == "setup":
        from environment import setup

        setup(apt_cache=not a.no_apt_cache)
        raise SystemExit()
    if a.command == "reset-environment":
        from environment import reset

        with p.lock():
            reset()
        raise SystemExit()
    if a.command == "audit":
        from audit import main

        with p.lock():
            raise SystemExit(main())
    if a.command == "export":
        from repository import export

        with p.lock():
            export(a.output, a.signing_home, a.key)
        raise SystemExit()
    selected = (
        list(p.packages())
        if a.all or a.command == "list" and not a.packages
        else a.packages
    )
    if not selected:
        parser.error("select package names or --all")
    modules = p.order(selected, a.with_deps)
    if a.command == "list":
        for m in modules:
            print(m + " " + p.recipe(m)[1])
    else:
        from environment import keep_sudo_alive

        with p.lock(), keep_sudo_alive() if a.command == "build" else nullcontext():
            if a.command == "clean" and a.all:
                from cleanup import has_generated_files

                modules = [
                    module
                    for module in modules
                    if has_generated_files(module, accepted=a.accepted)
                ]
                if not modules:
                    print("Nothing to clean")
            if a.command == "check":
                p.check(modules, a.baseline)
                print(f"{len(modules)} recipes and dependency graph checked")
            else:
                for i, m in enumerate(modules, 1):
                    print(f"[{i}/{len(modules)}] {a.command} {m}", flush=True)
                    if a.command == "clean":
                        from cleanup import clean

                        clean(m, accepted=a.accepted)
                    elif a.command == "fetch":
                        p.fetch(m, a.offline)
                    else:
                        target = p.prepare(m, a.offline)
                        if a.command == "build":
                            from environment import build

                            build(
                                m,
                                target,
                                jobs=a.jobs,
                                apt_cache=False if a.no_apt_cache else None,
                            )
except (ValueError, FileNotFoundError, BlockingIOError) as e:
    parser.exit(1, str(e) + "\n")
