# -*- coding: UTF-8 -*-

import sys
import importlib

from sys import argv
from os import system, getuid
from collections import OrderedDict
from signal import signal, SIGINT

from pyeole.translation.i18n import _
from pyeole.ansiprint import print_orange, \
                             print_red, print_blue, \
                             NOTPUT
from pyeole.common import get_current_column

importlib.reload(sys)


def prompt_boolean(prompt, interactive=True, default=False, default_uninteractive=None, level='info'):
    """Prompt the user and return her choice

    :param `str` prompt: prompt string to display to the user
    :param `bool` interactive: I don't know what's for
    :param `bool` default: default value
    :param `bool` default_interactive: default value if interactive is ``True``
    :param `str` level: log level
    """
    answer_mapping = OrderedDict(((True, [_('yes'), _('y')]),
                      (False, [_('no'), _('n')])))

    reverse_answer_mapping = {value: bool for bool, values in list(answer_mapping.items())
                              for value in values}

    boolean_answer = default

    # check parameters
    message_levels = {'info': print,
                      'warn': print_orange,
                      'err': print_red}
    if level not in message_levels:
        raise ValueError(_('question_ouinon : level must be "info", "warn" or "err"'))
    if default not in [True, False]:
        raise ValueError(_('question_ouinon : default must be "True" or "False"'))
    if default_uninteractive is None:
        default_uninteractive = default
    elif default_uninteractive not in [True, False]:
        raise ValueError(_('question_ouinon : default_uninteractive must be "True" or "False"'))

    default_uninteractive = default_uninteractive if default_uninteractive is not None else default

    if interactive is not True:
        boolean_answer = default_uninteractive
    else:
        message_levels[level](prompt + ' [{}]'.format('/'.join([a[0] for a in list(answer_mapping.values())])))
        answer = input(_('[{}]: ').format(answer_mapping[default][0])).lower()
        boolean_answer = reverse_answer_mapping.get(answer, default)

    return boolean_answer


def question_ouinon(question, interactive=True, default='non',
        default_uninteractive=None, level='info'):

    boolean_mapping = {'non': False,
                       'oui': True}
    if default not in ['non', 'oui']:
        raise ValueError(_('question_ouinon : default must be "oui" or "non"'))
    else:
        default = boolean_mapping[default]
    if default_uninteractive not in [None, 'oui', 'non']:
        raise ValueError(_('question_ouinon : default_uninteractive must be "oui" or "non"'))
    else:
        default_uninteractive = default_uninteractive if default_uninteractive is None else boolean_mapping[default_uninteractive]

    answer = prompt_boolean(question, interactive, default, default_uninteractive, level)
    if answer is True:
        return 'oui'
    elif answer is False:
        return 'non'


def print_title_rule(cols=None):
    """ print a title rule composed of '-'
    """
    if not cols:
        cols = get_current_column()

    try:
        print_blue('{:-^{col}}'.format('', col=cols))
    except ValueError:
        pass


def print_title(msg, cols=None):
    """ Print a title with this format :
        ###\t{message}\t###
    """
    if not cols:
        cols = get_current_column()

    try:
        output = "{:^{col}}".format(msg, col=cols)
        print_title_rule()
        print_blue(output)
        print_title_rule()
    except ValueError:
        print(msg)

def print_no_cr(msg, column=None):
    """ print a line align on right without '\n'
    """
    if not column:
        column = get_current_column()

    try:
        fstr = "{:<{col}}".format(msg, col=column)
        sys.stdout.write(fstr)
        sys.stdout.flush()
    except ValueError:
        print(msg)

def print_line(msg, column=None):
    """ print a line align on right with '\n'
    """
    if not column:
        column = get_current_column()

    try:
        fstr = "{:<{col}}\n".format(msg, col=column)
        sys.stdout.write(fstr)
        sys.stdout.flush()
    except ValueError:
        print(msg)

def nice_list_print(string_list, columns=None, silent=False):
    """ Print a python list nicely
    """
    separator = " "
    if not columns:
        columns = get_current_column()

    try:
        nb_col = columns / len(max(string_list))

        "Produce equal-width columns from string_list"
        sublists = []

        # empty_str based on item 0 of string_list
        try:
            empty_str = type(string_list[0])()
        except IndexError: # string_list is empty
            print("")

        # create a sublist for every column
        for col in range(nb_col):
            sublists.append(string_list[col::nb_col])

        # find maximum length of a column
        max_sublist_len = max(map(len, sublists))

        # make all columns same length
        for sublist in sublists:
            if len(sublist) < max_sublist_len:
                sublist.append(empty_str)

        # calculate a format string for the output lines
        format_str = separator.join(
            "%%-%ds" % max(map(len, sublist))
             for sublist in sublists)

        if silent:
            ret = []
            for line_items in zip(*sublists):
                ret.append(format_str % line_items)
            return ret
        for line_items in zip(*sublists):
            print(format_str % line_items)

    except ValueError:
        print(string_list)

def clear():
    """ Clear console if suitable
    """
    if not NOTPUT:
        system('clear')

def only_root():
    if getuid() != 0:
        print_red(_("{0} can only be launched by root").format(argv[0]))
        sys.exit(1)

def proper_exit(*args):
    """callback par défaut appelé lors d'un ctrl-c"""
    print(_("Cancelled by user."))
    sys.exit(1)

def catch_signal(exit_func=None):
    """gestion du ctrl-c"""
    if not exit_func:
        signal(SIGINT, proper_exit)
    else:
        signal(SIGINT, exit_func)
