import click
from click.parser import normalize_opt
from koapy.cli.extensions.functools import update_wrapper_with_click_params
[docs]class VerboseOption(click.Option):
    def __init__(self, *decls, **attrs):
        self._flag_value = attrs.pop("flag_value", None)
        super().__init__(*decls, **attrs)
        self._parser = None
        self._parser__match_long_opt = None
        self._parser__match_short_opt = None
        self._parser__get_value_from_state = None
    def _match_long_opt(self, opt, explicit_value, state):
        # pylint: disable=protected-access
        if opt in self.opts and opt in self._parser._long_opt:
            option = self._parser._long_opt[opt]
            option.action = "store"
        self._parser__match_long_opt(opt, explicit_value, state)
    def _match_short_opt(self, arg, state):
        # pylint: disable=protected-access
        prefix = arg[0]
        for ch in arg[1:]:
            opt = normalize_opt(f"{prefix}{ch}", self._parser.ctx)
            if opt in self.opts and opt in self._parser._short_opt:
                option = self._parser._short_opt[opt]
                option.action = "count"
        self._parser__match_short_opt(arg, state)
    def _get_value_from_state(self, option_name, option, state):
        # pylint: disable=protected-access
        try:
            value = self._parser__get_value_from_state(option_name, option, state)
        except click.BadOptionUsage:
            value = self._flag_value
        else:
            if option_name in self.opts:
                if (
                    isinstance(value, str)
                    and value[:1] in self._parser._opt_prefixes
                    and len(value) > 1
                ):
                    state.rargs.insert(0, value)
                    value = self._flag_value
        return value
    def _patch_parser(self, parser):
        # pylint: disable=protected-access
        self._parser = parser
        self._parser__match_short_opt = self._parser._match_short_opt
        self._parser._match_short_opt = self._match_short_opt
        self._parser__match_long_opt = self._parser._match_long_opt
        self._parser._match_long_opt = self._match_long_opt
        self._parser__get_value_from_state = self._parser._get_value_from_state
        self._parser._get_value_from_state = self._get_value_from_state
[docs]    def add_to_parser(self, parser, ctx):
        self._patch_parser(parser)
        super().add_to_parser(parser, ctx)  
[docs]def verbose_flag_option(
    default=0,
    flag_value=1,
    show_default=False,
    metavar="[0...5]",
    help="Set verbosity level.",
):
    # pylint: disable=redefined-builtin
    return click.option(
        "-v",
        "--verbose",
        type=int,
        default=default,
        flag_value=flag_value,
        show_default=show_default,
        metavar=metavar,
        help=help,
        cls=VerboseOption,
    ) 
[docs]def no_verbose_flag_option(
    help="Force zero verbosity.",
):
    # pylint: disable=redefined-builtin
    return click.option(
        "-s",
        "--no-verbose",
        "--slient",
        is_flag=True,
        default=False,
        help=help,
    ) 
[docs]def verbose_option(
    dest="verbose",
    default=0,
    flag_value=1,
    callback=None,
    expose_value=False,
    show_default=False,
):
    def decorator(f):
        @click.pass_context
        @verbose_flag_option(
            default=default,
            flag_value=flag_value,
            show_default=show_default,
        )
        @no_verbose_flag_option()
        def new_func(ctx, *args, **kwargs):
            verbose = kwargs.pop("verbose")
            no_verbose = kwargs.pop("no_verbose")
            if no_verbose:
                verbose = 0
            if expose_value:
                kwargs[dest] = verbose
            if callable(callback):
                param = ctx.params.get("verbose")
                value = verbose
                callback(ctx, param, value)
            return ctx.invoke(f, *args, **kwargs)
        return update_wrapper_with_click_params(new_func, f)
    return decorator