# Copyright 2024 The Fuchsia Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Custom argument actions for argparse."""

import argparse
import typing


class SelectionAction(argparse.Action):
    """Support appending selections to a single list in argparse.

    This action stores any value for the options in the destination.
    If multiple option strings are provided, use the longest as the canonical version.

    Example:
        parser.add_argument('-a', '--and', action=SelectionAction, dest='selection')
        parser.add_argument('selection', action=SelectionAction, dest='selection')
        assert (
            parser.parse_args(['value', '-a', 'other', '--and', 'another']).selection ==
            ['value', '--and', 'other', '--and', 'another']
        )
    """

    def __init__(
        self,
        option_strings: list[str],
        dest: str,
        nargs: int | str | None = None,
        **kwargs: typing.Any,
    ) -> None:
        """Create a SelectionAction.

        Args:
            option_strings (list[str]): List of options. See argparse documentation.
            dest (str): Destination variable. See argparse documentation.
            nargs (Optional[Union[int, str]]): Number of arguments. See argparse documentation.
        """

        self._dest = dest
        if nargs is None:
            nargs = "*"
        super().__init__(list(option_strings), dest, nargs=nargs, **kwargs)

    def __call__(
        self,
        parser: argparse.ArgumentParser,
        namespace: argparse.Namespace,
        values: typing.Sequence[str] | None,
        option_string: str | None = None,
    ) -> None:
        """Call this parser.

        See argparse documentation for details.
        """

        if not values:
            return

        if getattr(namespace, self._dest) is None:
            setattr(namespace, self._dest, [])
        lst: list[str] = getattr(namespace, self._dest)
        lst += SelectionAction._postprocess_args(list(values))

    _COMPONENT_REPLACE = "__COMPONENT_____"
    _PACKAGE_REPLACE = "__PACKAGE_____"
    _AND_REPLACE = "__AND_____"

    @classmethod
    def _postprocess_args(cls, arg_list: list[str]) -> list[str]:
        """Convert args back from stand-in positionals to canonical values.

        See preprocess_args for details.

        Args:
            arg_list (list[str]): Arguments to process.

        Returns:
            list[str]: Processed args, suitable for selection parsing.
        """
        canonical_mapping = {
            cls._COMPONENT_REPLACE: "--component",
            cls._PACKAGE_REPLACE: "--package",
            cls._AND_REPLACE: "--and",
        }
        for i in range(len(arg_list)):
            if arg_list[i] in canonical_mapping:
                arg_list[i] = canonical_mapping[arg_list[i]]
        return arg_list

    @classmethod
    def preprocess_args(cls, arg_list: list[str]) -> list[str]:
        """Handle known selection flags, converting them to positionals.

        Argparse really does not like interleaving positional arguments and
        switches, and when you do it does not preserve the ordering.

        We avoid this situation by converting each switch for which ordering is
        needed (-a, -c, -p) and converting them to a stand-in value which is
        not a switch. This will be passed verbatim as a positional argument,
        and can then be post-processed later to change back to the canonical
        flag names for selection processing.

        Args:
            arg_list (list[str]): Arguments to process.

        Returns:
            list[str]: Processed list, suitable to pass to argparse.
        """
        replace_mapping = {
            "-c": cls._COMPONENT_REPLACE,
            "--component": cls._COMPONENT_REPLACE,
            "-p": cls._PACKAGE_REPLACE,
            "--package": cls._PACKAGE_REPLACE,
            "-a": cls._AND_REPLACE,
            "--and": cls._AND_REPLACE,
        }
        for i in range(len(arg_list)):
            if arg_list[i] == "--":
                # Do not affect args meant to be passed to underlying programs.
                break
            elif arg_list[i] in replace_mapping:
                # Replace args with new names that will show as
                # interleaved positional args.
                arg_list[i] = replace_mapping[arg_list[i]]
        return arg_list


class InvalidAction(argparse.Action):
    """Argparse action that raises an exception if it is ever called.

    We pre-process certain command line flags so they are treated
    as positional arguments for the purpose of having an ordered
    list of selections interleaved with other flags. This action
    is used to catch bugs where we inadvertently allow such an
    argument to be handled by argparse itself.
    """

    def __init__(
        self,
        *args: typing.Any,
        **kwargs: typing.Any,
    ) -> None:
        super().__init__(*args, **kwargs)

    def __call__(
        self,
        parser: argparse.ArgumentParser,
        namespace: argparse.Namespace,
        values: typing.Sequence[str] | None,
        option_string: str | None = None,
    ) -> None:
        """Call this parser.

        See argparse documentation for details.
        """

        raise RuntimeError("This action should not be possible")
