"""Functions for obtaining CLI input"""

import termios
import signal
import sys
import os
from typing import Union
from . import color


def get_keypress() -> str:
    """Get a single keypress, the ugly POSIX way"""
    fileno = sys.stdin.fileno()
    old = termios.tcgetattr(fileno)
    new = termios.tcgetattr(fileno)
    new[3] = new[3] & ~termios.ICANON & ~termios.ECHO
    new[6][termios.VMIN] = 1
    new[6][termios.VTIME] = 0
    termios.tcsetattr(fileno, termios.TCSANOW, new)
    key = None
    try:
        key = str(os.read(fileno, 4), 'ascii')
    finally:
        termios.tcsetattr(fileno, termios.TCSAFLUSH, old)
    keylist = {
        '\t': 'TAB',
        '\n': 'ENTER',
        '\x7f': 'BACKSPACE',
        '\x1b': 'ESC',
        '\x1b[Z': 'BACKTAB',
        '\x1bOH': 'HOME',
        '\x1bOP': 'F1',
        '\x1bOQ': 'F2',
        '\x1bOR': 'F3',
        '\x1bOS': 'F4',
        '\x1b[15': 'F5',
        '\x1b[17': 'F6',
        '\x1b[18': 'F7',
        '\x1b[19': 'F8',
        '\x1b[20': 'F9',
        '\x1b[21': 'F10',
        '\x1b[23': 'F11',
        '\x1b[24': 'F12',
        '\x1b[A': 'ARROW_UP',
        '\x1b[B': 'ARROW_DN',
        '\x1b[C': 'ARROW_RT',
        '\x1b[D': 'ARROW_LT',
    }
    return key if key not in keylist else keylist[key]


get_keypress.__module__ = 'rads'


def _prompt_timeout(signum, _frame):
    raise TimeoutError("Prompt timed out")


def prompt_y_n(
    question: str,
    *,
    timeout: Union[int, None] = 604800,
    sigint_exit: bool = True,
) -> bool:
    """Prompt for a yes or no answer

    Args:
        question: text to display before [y/n] prompt
        timeout: time in seconds after which to raise TimeoutError. Defaults
          to one week
        sigint_exit: Whether to sys.exit(1) on ctrl+c; Defaults True.

    Raises:
        SystemExit: if SIGINT is received
        KeyboardInterrupt: if sigint_exit=False and a sigint is received
        TimeoutError: if timeout= is set and no response in that time
    """
    valid = {"yes": True, "y": True, "no": False, "n": False}
    while True:
        print(question, '[y/n]')
        try:
            if timeout:
                signal.signal(signal.SIGALRM, _prompt_timeout)
                signal.alarm(timeout)
            choice = input().lower()
            if timeout:
                signal.alarm(0)  # disable the alarm
        except KeyboardInterrupt:
            if not sigint_exit:
                raise
            print("\nCancelled")
            sys.exit(1)
        if choice in valid:
            return valid[choice]
        print('Invalid answer. Try again:', color.bold('[y/n]'))


prompt_y_n.__module__ = 'rads'
