# Copyright 1999-2020 Gentoo Authors
# Distributed under the terms of the GNU General Public License v2

import signal
import sys

from portage.output import bold, create_color_func


class UserQuery:
    """The UserQuery class is used to prompt the user with a set of responses,
    as well as accepting and handling the responses."""

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

    def query(self, prompt, enter_invalid, responses=None, colours=None):
        """Display a prompt and a set of responses, then waits for user input
        and check it against the responses. The first match is returned.

        An empty response will match the first value in the list of responses,
        unless enter_invalid is True. The input buffer is *not* cleared prior
        to the prompt!

        prompt: The String to display as a prompt.
        responses: a List of Strings with the acceptable responses.
        colours: a List of Functions taking and returning a String, used to
        process the responses for display. Typically these will be functions
        like red() but could be e.g. lambda x: "DisplayString".

        If responses is omitted, it defaults to ["Yes", "No"], [green, red].
        If only colours is omitted, it defaults to [bold, ...].

        Returns a member of the List responses. (If called without optional
        arguments, it returns "Yes" or "No".)

        KeyboardInterrupt is converted to SystemExit to avoid tracebacks being
        printed."""
        if responses is None:
            responses = ["Yes", "No"]
            colours = [
                create_color_func("PROMPT_CHOICE_DEFAULT"),
                create_color_func("PROMPT_CHOICE_OTHER"),
            ]
        elif colours is None:
            colours = [bold]
        colours = (colours * len(responses))[: len(responses)]
        responses = [
            (x.decode("utf-8", "replace") if isinstance(x, bytes) else x)
            for x in responses
        ]
        if "--alert" in self.myopts:
            prompt = "\a" + prompt
        print(bold(prompt), end=" ")
        try:
            while True:
                try:
                    response = input(
                        f"[{'/'.join([colours[i](responses[i]) for i in range(len(responses))])}] "
                    )
                except UnicodeDecodeError as e:
                    response = (
                        e.object.decode("utf-8", "replace")
                        if isinstance(e.object, bytes)
                        else e.object
                    ).rstrip("\n")
                if response or not enter_invalid:
                    for key in responses:
                        # An empty response will match the
                        # first value in responses.
                        if response.upper() == key[: len(response)].upper():
                            return key
                print(f"Sorry, response '{response}' not understood.", end=" ")
        except (EOFError, KeyboardInterrupt):
            print("Interrupted.")
            sys.exit(128 + signal.SIGINT)
