from ast import literal_eval
import readline
from typing import Any, Sequence


# -----------------------------------------------------------
def readline_input(prompt: str, prefill: str = '') -> str:
    """
    Print out default value for raw_input
    """
    readline.set_startup_hook(lambda: readline.insert_text(prefill))
    try:
        return input(prompt)
    finally:
        readline.set_startup_hook()


# -----------------------------------------------------------
def confirm_looper(question: str) -> str:
    """
    Get y/n response to question
    """
    inq = None
    while not inq:
        print()
        ans = input(question).lower()
        if ans not in ('y', 'n'):
            print("\nPlease select 'y' or 'n'")
            continue
        return ans
    return ''


# -----------------------------------------------------------
def convert_str_bool(dictionary: dict) -> dict:
    """
    Iterate over the dict keys and convert
    any bool-like string values to bool.
    """
    for k, v in dictionary.items():
        if not isinstance(v, str):
            continue
        v = v.lower()
        if v in ('true', 'ture', 'treu', 'true1'):
            dictionary[k] = True
        elif v in ('false', 'flase', 'fals', 'flas', 'false1'):
            dictionary[k] = False

    return dictionary


# -----------------------------------------------------------
def options_looper(options: Sequence[Any], msg: str, select_existing: bool = False) -> str:
    """
    Select item from list of options, with error checking
    to prevent user from selecting invalid number
    -options = list of options
    -msg = type of option being selected

    If select_existing is not required, give option to
    exit - possibly no existing option is correct
    """

    for i, t in enumerate(options):
        print(f'{i + 1} - {t}')

    selection = None
    count = len(options)

    if not select_existing:
        add_existing = confirm_looper(f'Select from existing {msg}? [y/n] ')

        if add_existing == 'n':
            return ''

    while not selection:
        try:
            choice = int(literal_eval(input(f'Select a {msg} number from the list above: '))) - 1
        except (ValueError, NameError, SyntaxError):
            print('\nERROR: Please enter an integer number\n')
            continue

        if 0 > choice or choice > count:
            print(f'\nERROR: Please select a valid {msg} from the list\n')
        else:
            selection = options[choice]
    return selection


__all__ = (
    'confirm_looper',
    'readline_input',
    'convert_str_bool',
    'options_looper',
)
