# Copyright 2024 The IREE Authors
#
# Licensed under the Apache License v2.0 with LLVM Exceptions.
# See https://llvm.org/LICENSE.txt for license information.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

from typing import Any, IO

import argparse
import importlib
import importlib.util
from pathlib import Path
import sys

from iree.build.executor import BuildEntrypoint, Entrypoint, Executor

__all__ = [
    "iree_build_main",
    "load_build_module",
]


def iree_build_main(
    module="__main__",
    args: list[str] | None = None,
    stdout: IO | None = None,
    stderr: IO | None = None,
):
    """Make a build module invoke iree.build on itself when run.

    Typically, if you have a module that declares build entrypoints, you will
    add a stanza at the end:

    .. code-block:: python
        from iree.build import *

        if __name__ == "__main__":
            iree_build_main()
    """
    main = CliMain(module=module, args=args, stdout=stdout, stderr=stderr)
    main.run()


def load_build_module(module_path: Path | str):
    """Loads a build module by path, evaling and returning it."""
    spec = importlib.util.spec_from_file_location("__iree_build__", module_path)
    mod = importlib.util.module_from_spec(spec)
    spec.loader.exec_module(mod)
    return mod


class CliMain:
    """Composes command line programs."""

    def __init__(
        self,
        *,
        args: list[str] | None = None,
        module=None,
        stdout: IO | None = None,
        stderr: IO | None = None,
    ):
        self.stdout = stdout if stdout is not None else sys.stdout
        self.stderr = stderr if stderr is not None else sys.stderr
        if args is None:
            args = sys.argv[1:]
        if module is not None and isinstance(module, str):
            module = __import__(module)
        module = module

        p = self.arg_parser = argparse.ArgumentParser(
            description="IREE program build driver"
        )
        if module is None:
            args, self.top_module = self._resolve_module_arguments(args)
        else:
            self.top_module = ModuleWrapper(module)

        p.add_argument(
            "--output-dir",
            type=Path,
            default=Path.cwd(),
            help="Output directory for the build tree (defaults to current directory)",
        )

        cmd_group_desc = p.add_argument_group(
            title="Build command",
            description="Selects a build sub-command to invoke (default '--build')",
        )
        cmd_group = cmd_group_desc.add_mutually_exclusive_group()
        cmd_group.add_argument(
            "--build",
            dest="command",
            action="store_const",
            const=self.build_command,
            help="Executes build actions",
        )
        cmd_group.add_argument(
            "--list",
            dest="command",
            action="store_const",
            const=self.list_command,
            help="Lists top level build actions",
        )

        cmd_group.add_argument(
            "--list-all",
            dest="command",
            action="store_const",
            const=self.list_all_command,
            help="Lists all build actions",
        )

        p.add_argument(
            "action_path",
            nargs="*",
            help="Paths of actions to build (default to top-level actions)",
        )

        self._define_action_arguments(p)
        self.args = self.arg_parser.parse_args(args)

    def abort(self):
        sys.exit(1)

    def _define_action_arguments(self, p: argparse.ArgumentParser):
        user_group = p.add_argument_group("Action defined options")
        for ep in self.top_module.entrypoints.values():
            for cl_arg in ep.cl_args():
                cl_arg.define_arg(user_group)

    def _resolve_module_arguments(
        self, args: list[str]
    ) -> tuple[list[str], "ModuleWrapper"]:
        p = argparse.ArgumentParser(
            add_help=False,
            usage="python -m iree.build [-m] build_module [... additional module specific options ...]",
            prog="python -m iree.build",
        )
        # Invoked as a standalone tool: need the user to specify the
        # module.
        p.add_argument(
            "-m",
            dest="parse_as_module",
            action="store_true",
            help="Interpret the build definitions argument as a module (vs a file)",
        )
        p.add_argument(
            "build_module",
            help="The Python file or module from which to load build definitions",
        )

        bootstrap_args, rem_args = p.parse_known_args(args)
        # Resolve from arguments.
        is_module = bootstrap_args.parse_as_module or _is_module_like_str(
            bootstrap_args.build_module
        )
        if is_module:
            try:
                top_module = ModuleWrapper.load_module(bootstrap_args.build_module)
            except ModuleNotFoundError as e:
                print(
                    f"ERROR: Module '{bootstrap_args.build_module}' not found: {e}",
                    file=self.stderr,
                )
                self.abort()
        else:
            top_module = ModuleWrapper.load_py_file(bootstrap_args.build_module)
        return rem_args, top_module

    def _create_executor(self) -> Executor:
        executor = Executor(self.args.output_dir, self.args, stderr=self.stderr)
        executor.analyze(*self.top_module.entrypoints.values())
        return executor

    def run(self):
        command = self.args.command
        if command is None:
            command = self.build_command
        command()

    def build_command(self):
        executor = self._create_executor()

        if not self.args.action_path:
            # Default to all.
            build_actions = list(executor.entrypoints)
        else:
            # Look up each requested and add it.
            build_actions = []
            for action_path in self.args.action_path:
                try:
                    build_actions.append(executor.all[action_path])
                except KeyError:
                    all_paths = "\n".join(executor.all.keys())
                    print(
                        f"ERROR: Action '{action_path}' not found. Available: \n{all_paths}",
                        file=self.stderr,
                    )
                    self.abort()
        executor.build(*build_actions)

        for build_action in build_actions:
            if isinstance(build_action, BuildEntrypoint):
                for output in build_action.outputs:
                    print(f"{output.get_fs_path()}", file=self.stdout)

    def list_command(self):
        executor = self._create_executor()
        for ep in executor.entrypoints:
            print(ep.path, file=self.stdout)

    def list_all_command(self):
        executor = self._create_executor()
        for name in executor.all.keys():
            if name:
                print(name, file=self.stdout)


class ModuleWrapper:
    """Wraps a raw, loaded module with access to discovered details."""

    def __init__(self, mod):
        self.mod = mod
        self.entrypoints = self._collect_entrypoints()

    @staticmethod
    def load_module(module_name: str) -> "ModuleWrapper":
        return ModuleWrapper(importlib.import_module(module_name))

    @staticmethod
    def load_py_file(module_path: Path | str) -> "ModuleWrapper":
        return ModuleWrapper(load_build_module(str(module_path)))

    def _collect_entrypoints(self) -> dict[str, Entrypoint]:
        results: dict[str, Entrypoint] = {}
        for attr_name, attr_value in self.mod.__dict__.items():
            if isinstance(attr_value, Entrypoint):
                results[attr_name] = attr_value
        return results


def _is_module_like_str(s: str) -> bool:
    return "/" not in s and "\\" not in s and not s.endswith(".py")
