from __future__ import print_function, unicode_literals
from util.log import log


class ChangeSeverity:
    """
    How much should the user be involved during the installation? A default
    level specified either in the profile or supplied at the beginning of the
    installation is used to gauge whether an operation needs confirmation from
    the user first or not.
    """
    # fully automated installation
    AUTOMATED = 0
    # important, hard to reverse changes
    CRITICAL = 1
    # semi-important changes
    NORMAL = 2
    # typically users wouldn't bother reviewing these changes
    TRIVIAL = 3

    # default severity chosen by the user
    default = CRITICAL

    @staticmethod
    def update_default_severity(profile):
        """
        Update the default severity if necessary.
        """
        if profile.auto:
            ChangeSeverity.default = ChangeSeverity.AUTOMATED

    @staticmethod
    def applicable(change_severity):
        """
        Check if the given severity is applicable for the user choice of default
        severity.
        """
        return ChangeSeverity.default >= change_severity


def get_user_input(question):
    import sys
    if sys.version_info[0] < 3:
        # Python 2.x
        return raw_input(question)
    else:
        # Python 3.x
        return input(question)


def user_confirmed_change(question, change_severity=ChangeSeverity.TRIVIAL):
    """
    If the given change_severity is applicable according to the user choice of
    default severity, the question will be presented to the user with a Yes/No
    choice.
    :param question: the message to be presented to the user.
    It shall not end with a question mark, and a "Yes/No" is automatically added.
    :param change_severity: the seriousness of the change waiting to be done
    :rtype boolean: return True if the change severity is below the default level,
    or if it is applicable and the user selects "Yes".
    """
    ret = True
    if ChangeSeverity.applicable(change_severity):
        if question is not None and question != "":
            try:
                if question[-1] != "?":
                    question += "?"
                question += " [Y/n] "
                user_input = get_user_input(question)
                ret = (user_input == "" or user_input.lower() == "y")
            except KeyboardInterrupt:
                print("")
                log.info("Installation interrupted by user with Ctrl-C, exiting.")
                exit(1)
    return ret


def set_severity_choice():
    """
    Presents a prompt for selecting a severity level. The default severity
    level in ChangeSeverity is automatically updated if needed.
    """
    if ChangeSeverity.applicable(ChangeSeverity.CRITICAL):
        try:
            question = "\nSelect the level of interactivity during the installation:\n" + \
                       " 0 - automated, do not ask any questions\n" + \
                       " 1 - critical, ask before any potentially hard to reverse changes\n" + \
                       " 2 - normal, ask before typically safe changes as well, reverting is possible\n" + \
                       " 3 - trivial, verify every possible system change\n" + \
                       " [0/1/2/3] (Default: 1) > "
            user_input = get_user_input(question)
            try:
                if user_input != "":
                    choice = int(user_input)
                    if choice not in [0, 1, 2, 3]:
                        log.warn("Invalid choice: '{}', please specify one of 0, 1, 2 or 3.".format(user_input))
                        set_severity_choice()
                    else:
                        ChangeSeverity.default = choice
            except (ValueError, TypeError):
                log.warn("Invalid choice: '{}', please specify one of 0, 1, 2 or 3.".format(user_input))
                set_severity_choice()
        except KeyboardInterrupt:
            print("")
            log.info("Installation interrupted by user with Ctrl-C, exiting.")
            exit(1)
