# Copyright 2012 The ChromiumOS Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""Module that contains meta-logic related to CLI commands.

This module contains two important definitions used by all commands:
    CliCommand: The parent class of all CLI commands.
    command_decorator: Decorator that must be used to ensure that the command
        shows up in |_commands| and is discoverable.

Commands can be either imported directly or looked up using this module's
ListCommands() function.
"""

import importlib
import logging
import os
import sys

from chromite.lib import commandline
from chromite.lib import constants
from chromite.lib import cros_build_lib


# Paths for finding and importing subcommand modules.
_SUBCOMMAND_MODULE_DIRECTORY = os.path.join(os.path.dirname(__file__), "cros")
_SUBCOMMAND_MODULE_PREFIX = "cros_"


_commands = {}


def UseProgressBar():
    """Determine whether the progress bar is to be used or not.

    We only want the progress bar to display for the brillo commands which
    operate at logging level NOTICE. If the user wants to see the noisy output,
    then they can execute the command at logging level INFO or DEBUG.
    """
    return logging.getLogger().getEffectiveLevel() == logging.NOTICE


def ImportCommand(name):
    """Directly import the specified subcommand.

    This method imports the module which must contain the single subcommand.
    When the module is loaded, the declared command (those that use
    command_decorator) will automatically get added to |_commands|.

    Args:
        name: The subcommand to load.

    Returns:
        A reference to the subcommand class.
    """
    module_path = os.path.join(
        _SUBCOMMAND_MODULE_DIRECTORY, "cros_%s" % (name.replace("-", "_"),)
    )
    import_path = os.path.relpath(
        os.path.realpath(module_path), constants.CHROMITE_DIR.parent
    )
    module_parts = import_path.split(os.path.sep)
    importlib.import_module(".".join(module_parts))
    return _commands[name]


def ListCommands():
    """Return the set of available subcommands.

    We assume that there is a direct one-to-one relationship between the module
    name on disk and the command that module implements.  We assume this as a
    performance requirement (to avoid importing every subcommand every time even
    though we'd only ever run a single one), and to avoid 3rd party module usage
    in one subcommand breaking all other subcommands (not a great solution).
    """
    # Filenames use underscores due to python naming limitations, but
    # subcommands use dashes as they're easier for humans to type.
    # Strip off the leading "cros_" and the trailing ".py".
    return set(
        x[5:-3].replace("_", "-")
        for x in os.listdir(_SUBCOMMAND_MODULE_DIRECTORY)
        if (
            x.startswith(_SUBCOMMAND_MODULE_PREFIX)
            and x.endswith(".py")
            and not x.endswith("_unittest.py")
        )
    )


class InvalidCommandError(Exception):
    """Error that occurs when command class fails validity checks."""


def command_decorator(name):
    """Decorator to check validity and add class to list of usable commands."""

    def inner_decorator(original_class):
        """Inner Decorator that actually wraps the class."""
        if not hasattr(original_class, "__doc__"):
            raise InvalidCommandError(
                "All handlers must have docstrings: %s" % original_class
            )

        if not issubclass(original_class, CliCommand):
            raise InvalidCommandError(
                "All Commands must derive from CliCommand: %s" % original_class
            )

        _commands[name] = original_class
        original_class.name = name

        return original_class

    return inner_decorator


class CliCommand:
    """All CLI commands must derive from this class.

    This class provides the abstract interface for all CLI commands. When
    designing a new command, you must sub-class from this class and use the
    command_decorator decorator. You must specify a class docstring as that will
    be used as the usage for the sub-command.

    In addition your command should implement AddParser which is passed in a
    parser that you can add your own custom arguments. See argparse for more
    information.
    """

    # Indicates whether command uses cache related commandline options.
    use_caching_options = False
    # Whether command uses dry-run options.
    use_dryrun_options = False

    # Indicates whether command uses filter related commandline options.
    use_filter_options = False

    def __init__(self, options):
        self.options = options

    @classmethod
    def AddParser(cls, parser):
        """Add arguments for this command to the parser."""
        parser.set_defaults(command_class=cls)

    @classmethod
    def ProcessOptions(
        cls,
        parser: commandline.ArgumentParser,
        options: commandline.ArgumentNamespace,
    ) -> None:
        """Validate & post-process options before freezing."""

    @classmethod
    def AddDeviceArgument(
        cls, parser, schemes=commandline.DEVICE_SCHEME_SSH, positional=False
    ):
        """Add a device argument to the parser.

        This standardizes the help message across all subcommands.

        Args:
            parser: The parser to add the device argument to.
            schemes: List of device schemes or single scheme to allow.
            positional: Whether it should be a positional or named argument.
        """
        help_strings = []
        schemes = list(cros_build_lib.iflatten_instance(schemes))
        if commandline.DEVICE_SCHEME_SSH in schemes:
            help_strings.append(
                "Target a device with [user@]hostname[:port]. "
                "IPv4/IPv6 addresses are allowed, but IPv6 must "
                "use brackets (e.g. [::1])."
            )
        if commandline.DEVICE_SCHEME_USB in schemes:
            help_strings.append("Target removable media with usb://[path].")
        if commandline.DEVICE_SCHEME_SERVO in schemes:
            help_strings.append(
                "Target a servo by port or serial number with "
                "servo:port[:port] or servo:serial:serial-number. "
                "e.g. servo:port:1234 or servo:serial:C1230024192."
            )
        if commandline.DEVICE_SCHEME_FILE in schemes:
            help_strings.append("Target a local file with file://path.")
        if positional:
            parser.add_argument(
                "device",
                type=commandline.DeviceParser(schemes),
                help=" ".join(help_strings),
            )
        else:
            parser.add_argument(
                "-d",
                "--device",
                type=commandline.DeviceParser(schemes),
                help=" ".join(help_strings),
            )

    def Run(self):
        """The command to run."""
        raise NotImplementedError()

    def TranslateToChrootArgv(self):
        """Hook to get the argv for reexecution inside the chroot.

        By default, return the same args used to execute it in the first place.
        Hook allows commands to translate specific arguments, i.e. change paths
        to chroot paths.
        """
        return sys.argv[:]
