# Copyright (c) 2024 Basalte bv
#
# SPDX-License-Identifier: Apache-2.0

import argparse
import os
import subprocess
import sys
import textwrap
from itertools import chain
from pathlib import Path

from west.commands import WestCommand
from zephyr_ext_common import ZEPHYR_BASE

sys.path.append(os.fspath(Path(__file__).parent.parent))
import zephyr_module


def in_venv() -> bool:
    return sys.prefix != sys.base_prefix


class Packages(WestCommand):
    def __init__(self):
        super().__init__(
            "packages",
            "manage packages for Zephyr",
            "List and Install packages for Zephyr and modules",
            accepts_unknown_args=True,
        )

    def do_add_parser(self, parser_adder):
        parser = parser_adder.add_parser(
            self.name,
            help=self.help,
            description=self.description,
            formatter_class=argparse.RawDescriptionHelpFormatter,
            epilog=textwrap.dedent(
                """
            Listing packages:

                Run 'west packages <manager>' to list all dependencies
                available from a given package manager, already
                installed and not. These can be filtered by module,
                see 'west packages <manager> --help' for details.
            """
            ),
        )

        parser.add_argument(
            "-m",
            "--module",
            action="append",
            default=[],
            dest="modules",
            metavar="<module>",
            help="Zephyr module to run the 'packages' command for. "
            "Use 'zephyr' if the 'packages' command should run for Zephyr itself. "
            "Option can be passed multiple times. "
            "If this option is not given, the 'packages' command will run for Zephyr "
            "and all modules.",
        )

        subparsers_gen = parser.add_subparsers(
            metavar="<manager>",
            dest="manager",
            help="select a manager.",
            required=True,
        )

        pip_parser = subparsers_gen.add_parser(
            "pip",
            help="manage pip packages",
            formatter_class=argparse.RawDescriptionHelpFormatter,
            epilog=textwrap.dedent(
                """
            Manage pip packages:

                Run 'west packages pip' to print all requirement files needed by
                Zephyr and modules.

                The output is compatible with the requirements file format itself.
            """
            ),
        )

        pip_parser.add_argument(
            "--install",
            action="store_true",
            help="Install pip requirements instead of listing them. "
            "A single 'pip install' command is built and executed. "
            "Additional pip arguments can be passed after a -- separator "
            "from the original 'west packages pip --install' command. For example pass "
            "'--dry-run' to pip not to actually install anything, but print what would be.",
        )

        pip_parser.add_argument(
            "--ignore-venv-check",
            action="store_true",
            help="Ignore the virtual environment check. "
            "This is useful when running 'west packages pip --install' "
            "in a CI environment where the virtual environment is not set up.",
        )

        return parser

    def do_run(self, args, unknown):
        if len(unknown) > 0 and unknown[0] != "--":
            self.die(
                f'Unknown argument "{unknown[0]}"; '
                'arguments for the manager should be passed after "--"'
            )

        # Store the zephyr modules for easier access
        self.zephyr_modules = zephyr_module.parse_modules(ZEPHYR_BASE, self.manifest)

        if args.modules:
            # Check for unknown module names
            module_names = [m.meta.get("name") for m in self.zephyr_modules]
            module_names.append("zephyr")
            for m in args.modules:
                if m not in module_names:
                    self.die(f'Unknown zephyr module "{m}"')

        if args.manager == "pip":
            return self.do_run_pip(args, unknown[1:])

        # Unreachable but print an error message if an implementation is missing.
        self.die(f'Unsupported package manager: "{args.manager}"')

    def do_run_pip(self, args, manager_args):
        requirements = []

        if not args.modules or "zephyr" in args.modules:
            requirements.append(ZEPHYR_BASE / "scripts/requirements.txt")

        for module in self.zephyr_modules:
            module_name = module.meta.get("name")
            if args.modules and module_name not in args.modules:
                if args.install:
                    self.dbg(f"Skipping module {module_name}")
                continue

            # Get the optional pip section from the package managers
            pip = module.meta.get("package-managers", {}).get("pip")
            if pip is None:
                if args.install:
                    self.dbg(f"Nothing to install for {module_name}")
                continue

            # Add requirements files
            requirements += [Path(module.project) / r for r in pip.get("requirement-files", [])]

        if args.install:
            if not in_venv() and not args.ignore_venv_check:
                self.die("Running pip install outside of a virtual environment")

            if len(requirements) > 0:
                subprocess.check_call(
                    [sys.executable, "-m", "pip", "install"]
                    + list(chain.from_iterable([("-r", r) for r in requirements]))
                    + manager_args
                )
            else:
                self.inf("Nothing to install")
            return

        if len(manager_args) > 0:
            self.die(f'west packages pip does not support unknown arguments: "{manager_args}"')

        self.inf("\n".join([f"-r {r}" for r in requirements]))
