# Copyright (c) 2021
#
# Authors:
#  Niteesh Babu G S <niteesh.gs@gmail.com>
#
# This work is licensed under the terms of the GNU LGPL, version 2 or
# later.  See the COPYING file in the top-level directory.
"""
QMP TUI

QMP TUI is an asynchronous interface built on top the of the QMP library.
It is the successor of QMP-shell and is bought-in as a replacement for it.

Example Usage: qmp-tui <SOCKET | TCP IP:PORT>
Full Usage: qmp-tui --help
"""

import argparse
import asyncio
import json
import logging
from logging import Handler, LogRecord
import signal
from typing import (
    List,
    Optional,
    Tuple,
    Type,
    Union,
    cast,
)

from pygments import lexers
from pygments import token as Token
import urwid
import urwid_readline

from .error import ProtocolError
from .legacy import QEMUMonitorProtocol, QMPBadPortError
from .message import DeserializationError, Message, UnexpectedTypeError
from .protocol import ConnectError, Runstate
from .qmp_client import ExecInterruptedError, QMPClient
from .util import create_task, pretty_traceback


# The name of the signal that is used to update the history list
UPDATE_MSG: str = 'UPDATE_MSG'


palette = [
    (Token.Punctuation, '', '', '', 'h15,bold', 'g7'),
    (Token.Text, '', '', '', '', 'g7'),
    (Token.Name.Tag, '', '', '', 'bold,#f88', 'g7'),
    (Token.Literal.Number.Integer, '', '', '', '#fa0', 'g7'),
    (Token.Literal.String.Double, '', '', '', '#6f6', 'g7'),
    (Token.Keyword.Constant, '', '', '', '#6af', 'g7'),
    ('DEBUG', '', '', '', '#ddf', 'g7'),
    ('INFO', '', '', '', 'g100', 'g7'),
    ('WARNING', '', '', '', '#ff6', 'g7'),
    ('ERROR', '', '', '', '#a00', 'g7'),
    ('CRITICAL', '', '', '', '#a00', 'g7'),
    ('background', '', 'black', '', '', 'g7'),
]


def format_json(msg: str) -> str:
    """
    Formats valid/invalid multi-line JSON message into a single-line message.

    Formatting is first tried using the standard json module. If that fails
    due to an decoding error then a simple string manipulation is done to
    achieve a single line JSON string.

    Converting into single line is more asthetically pleasing when looking
    along with error messages.

    Eg:
    Input:
          [ 1,
            true,
            3 ]
    The above input is not a valid QMP message and produces the following error
    "QMP message is not a JSON object."
    When displaying this in TUI in multiline mode we get

        [ 1,
          true,
          3 ]: QMP message is not a JSON object.

    whereas in singleline mode we get the following

        [1, true, 3]: QMP message is not a JSON object.

    The single line mode is more asthetically pleasing.

    :param msg:
        The message to formatted into single line.

    :return: Formatted singleline message.
    """
    try:
        msg = json.loads(msg)
        return str(json.dumps(msg))
    except json.decoder.JSONDecodeError:
        msg = msg.replace('\n', '')
        words = msg.split(' ')
        words = list(filter(None, words))
        return ' '.join(words)


def has_handler_type(logger: logging.Logger,
                     handler_type: Type[Handler]) -> bool:
    """
    The Logger class has no interface to check if a certain type of handler is
    installed or not. So we provide an interface to do so.

    :param logger:
        Logger object
    :param handler_type:
        The type of the handler to be checked.

    :return: returns True if handler of type `handler_type`.
    """
    for handler in logger.handlers:
        if isinstance(handler, handler_type):
            return True
    return False


class App(QMPClient):
    """
    Implements the QMP TUI.

    Initializes the widgets and starts the urwid event loop.

    :param address:
        Address of the server to connect to.
    :param num_retries:
        The number of times to retry before stopping to reconnect.
    :param retry_delay:
        The delay(sec) before each retry
    """
    def __init__(self, address: Union[str, Tuple[str, int]], num_retries: int,
                 retry_delay: Optional[int]) -> None:
        urwid.register_signal(type(self), UPDATE_MSG)
        self.window = Window(self)
        self.address = address
        self.aloop: Optional[asyncio.AbstractEventLoop] = None
        self.num_retries = num_retries
        self.retry_delay = retry_delay if retry_delay else 2
        self.retry: bool = False
        self.exiting: bool = False
        super().__init__()

    def add_to_history(self, msg: str, level: Optional[str] = None) -> None:
        """
        Appends the msg to the history list.

        :param msg:
            The raw message to be appended in string type.
        """
        urwid.emit_signal(self, UPDATE_MSG, msg, level)

    def _cb_outbound(self, msg: Message) -> Message:
        """
        Callback: outbound message hook.

        Appends the outgoing messages to the history box.

        :param msg: raw outbound message.
        :return: final outbound message.
        """
        str_msg = str(msg)

        if not has_handler_type(logging.getLogger(), TUILogHandler):
            logging.debug('Request: %s', str_msg)
        self.add_to_history('<-- ' + str_msg)
        return msg

    def _cb_inbound(self, msg: Message) -> Message:
        """
        Callback: outbound message hook.

        Appends the incoming messages to the history box.

        :param msg: raw inbound message.
        :return: final inbound message.
        """
        str_msg = str(msg)

        if not has_handler_type(logging.getLogger(), TUILogHandler):
            logging.debug('Request: %s', str_msg)
        self.add_to_history('--> ' + str_msg)
        return msg

    async def _send_to_server(self, msg: Message) -> None:
        """
        This coroutine sends the message to the server.
        The message has to be pre-validated.

        :param msg:
            Pre-validated message to be to sent to the server.

        :raise Exception: When an unhandled exception is caught.
        """
        try:
            await self._raw(msg, assign_id='id' not in msg)
        except ExecInterruptedError as err:
            logging.info('Error server disconnected before reply %s', str(err))
            self.add_to_history('Server disconnected before reply', 'ERROR')
        except Exception as err:
            logging.error('Exception from _send_to_server: %s', str(err))
            raise err

    def cb_send_to_server(self, raw_msg: str) -> None:
        """
        Validates and sends the message to the server.
        The raw string message is first converted into a Message object
        and is then sent to the server.

        :param raw_msg:
            The raw string message to be sent to the server.

        :raise Exception: When an unhandled exception is caught.
        """
        try:
            msg = Message(bytes(raw_msg, encoding='utf-8'))
            create_task(self._send_to_server(msg))
        except (DeserializationError, UnexpectedTypeError) as err:
            raw_msg = format_json(raw_msg)
            logging.info('Invalid message: %s', err.error_message)
            self.add_to_history(f'{raw_msg}: {err.error_message}', 'ERROR')

    def unhandled_input(self, key: str) -> None:
        """
        Handle's keys which haven't been handled by the child widgets.

        :param key:
            Unhandled key
        """
        if key == 'esc':
            self.kill_app()

    def kill_app(self) -> None:
        """
        Initiates killing of app. A bridge between asynchronous and synchronous
        code.
        """
        create_task(self._kill_app())

    async def _kill_app(self) -> None:
        """
        This coroutine initiates the actual disconnect process and calls
        urwid.ExitMainLoop() to kill the TUI.

        :raise Exception: When an unhandled exception is caught.
        """
        self.exiting = True
        await self.disconnect()
        logging.debug('Disconnect finished. Exiting app')
        raise urwid.ExitMainLoop()

    async def disconnect(self) -> None:
        """
        Overrides the disconnect method to handle the errors locally.
        """
        try:
            await super().disconnect()
        except (OSError, EOFError) as err:
            logging.info('disconnect: %s', str(err))
            self.retry = True
        except ProtocolError as err:
            logging.info('disconnect: %s', str(err))
        except Exception as err:
            logging.error('disconnect: Unhandled exception %s', str(err))
            raise err

    def _set_status(self, msg: str) -> None:
        """
        Sets the message as the status.

        :param msg:
            The message to be displayed in the status bar.
        """
        self.window.footer.set_text(msg)

    def _get_formatted_address(self) -> str:
        """
        Returns a formatted version of the server's address.

        :return: formatted address
        """
        if isinstance(self.address, tuple):
            host, port = self.address
            addr = f'{host}:{port}'
        else:
            addr = f'{self.address}'
        return addr

    async def _initiate_connection(self) -> Optional[ConnectError]:
        """
        Tries connecting to a server a number of times with a delay between
        each try. If all retries failed then return the error faced during
        the last retry.

        :return: Error faced during last retry.
        """
        current_retries = 0
        err = None

        # initial try
        await self.connect_server()
        while self.retry and current_retries < self.num_retries:
            logging.info('Connection Failed, retrying in %d', self.retry_delay)
            status = f'[Retry #{current_retries} ({self.retry_delay}s)]'
            self._set_status(status)

            await asyncio.sleep(self.retry_delay)

            err = await self.connect_server()
            current_retries += 1
        # If all retries failed report the last error
        if err:
            logging.info('All retries failed: %s', err)
            return err
        return None

    async def manage_connection(self) -> None:
        """
        Manage the connection based on the current run state.

        A reconnect is issued when the current state is IDLE and the number
        of retries is not exhausted.
        A disconnect is issued when the current state is DISCONNECTING.
        """
        while not self.exiting:
            if self.runstate == Runstate.IDLE:
                err = await self._initiate_connection()
                # If retry is still true then, we have exhausted all our tries.
                if err:
                    self._set_status(f'[Error: {err.error_message}]')
                else:
                    addr = self._get_formatted_address()
                    self._set_status(f'[Connected {addr}]')
            elif self.runstate == Runstate.DISCONNECTING:
                self._set_status('[Disconnected]')
                await self.disconnect()
                # check if a retry is needed
                if self.runstate == Runstate.IDLE:
                    continue
            await self.runstate_changed()

    async def connect_server(self) -> Optional[ConnectError]:
        """
        Initiates a connection to the server at address `self.address`
        and in case of a failure, sets the status to the respective error.
        """
        try:
            await self.connect(self.address)
            self.retry = False
        except ConnectError as err:
            logging.info('connect_server: ConnectError %s', str(err))
            self.retry = True
            return err
        return None

    def run(self, debug: bool = False) -> None:
        """
        Starts the long running co-routines and the urwid event loop.

        :param debug:
            Enables/Disables asyncio event loop debugging
        """
        screen = urwid.raw_display.Screen()
        screen.set_terminal_properties(256)

        self.aloop = asyncio.get_event_loop()
        self.aloop.set_debug(debug)

        # Gracefully handle SIGTERM and SIGINT signals
        cancel_signals = [signal.SIGTERM, signal.SIGINT]
        for sig in cancel_signals:
            self.aloop.add_signal_handler(sig, self.kill_app)

        event_loop = urwid.AsyncioEventLoop(loop=self.aloop)
        main_loop = urwid.MainLoop(urwid.AttrMap(self.window, 'background'),
                                   unhandled_input=self.unhandled_input,
                                   screen=screen,
                                   palette=palette,
                                   handle_mouse=True,
                                   event_loop=event_loop)

        create_task(self.manage_connection(), self.aloop)
        try:
            main_loop.run()
        except Exception as err:
            logging.error('%s\n%s\n', str(err), pretty_traceback())
            raise err


class StatusBar(urwid.Text):
    """
    A simple statusbar modelled using the Text widget. The status can be
    set using the set_text function. All text set is aligned to right.

    :param text: Initial text to be displayed. Default is empty str.
    """
    def __init__(self, text: str = ''):
        super().__init__(text, align='right')


class Editor(urwid_readline.ReadlineEdit):
    """
    A simple editor modelled using the urwid_readline.ReadlineEdit widget.
    Mimcs GNU readline shortcuts and provides history support.

    The readline shortcuts can be found below:
    https://github.com/rr-/urwid_readline#features

    Along with the readline features, this editor also has support for
    history. Pressing the 'up'/'down' switches between the prev/next messages
    available in the history.

    Currently there is no support to save the history to a file. The history of
    previous commands is lost on exit.

    :param parent: Reference to the TUI object.
    """
    def __init__(self, parent: App) -> None:
        super().__init__(caption='> ', multiline=True)
        self.parent = parent
        self.history: List[str] = []
        self.last_index: int = -1
        self.show_history: bool = False

    def keypress(self, size: Tuple[int, int], key: str) -> Optional[str]:
        """
        Handles the keypress on this widget.

        :param size:
            The current size of the widget.
        :param key:
            The key to be handled.

        :return: Unhandled key if any.
        """
        msg = self.get_edit_text()
        if key == 'up' and not msg:
            # Show the history when 'up arrow' is pressed with no input text.
            # NOTE: The show_history logic is necessary because in 'multiline'
            # mode (which we use) 'up arrow' is used to move between lines.
            if not self.history:
                return None
            self.show_history = True
            last_msg = self.history[self.last_index]
            self.set_edit_text(last_msg)
            self.edit_pos = len(last_msg)
        elif key == 'up' and self.show_history:
            self.last_index = max(self.last_index - 1, -len(self.history))
            self.set_edit_text(self.history[self.last_index])
            self.edit_pos = len(self.history[self.last_index])
        elif key == 'down' and self.show_history:
            if self.last_index == -1:
                self.set_edit_text('')
                self.show_history = False
            else:
                self.last_index += 1
                self.set_edit_text(self.history[self.last_index])
                self.edit_pos = len(self.history[self.last_index])
        elif key == 'meta enter':
            # When using multiline, enter inserts a new line into the editor
            # send the input to the server on alt + enter
            self.parent.cb_send_to_server(msg)
            self.history.append(msg)
            self.set_edit_text('')
            self.last_index = -1
            self.show_history = False
        else:
            self.show_history = False
            self.last_index = -1
            return cast(Optional[str], super().keypress(size, key))
        return None


class EditorWidget(urwid.Filler):
    """
    Wrapper around the editor widget.

    The Editor is a flow widget and has to wrapped inside a box widget.
    This class wraps the Editor inside filler widget.

    :param parent: Reference to the TUI object.
    """
    def __init__(self, parent: App) -> None:
        super().__init__(Editor(parent), valign='top')


class HistoryBox(urwid.ListBox):
    """
    This widget is modelled using the ListBox widget, contains the list of
    all messages both QMP messages and log messsages to be shown in the TUI.

    The messages are urwid.Text widgets. On every append of a message, the
    focus is shifted to the last appended message.

    :param parent: Reference to the TUI object.
    """
    def __init__(self, parent: App) -> None:
        self.parent = parent
        self.history = urwid.SimpleFocusListWalker([])
        super().__init__(self.history)

    def add_to_history(self,
                       history: Union[str, List[Tuple[str, str]]]) -> None:
        """
        Appends a message to the list and set the focus to the last appended
        message.

        :param history:
            The history item(message/event) to be appended to the list.
        """
        self.history.append(urwid.Text(history))
        self.history.set_focus(len(self.history) - 1)

    def mouse_event(self, size: Tuple[int, int], _event: str, button: float,
                    _x: int, _y: int, focus: bool) -> None:
        # Unfortunately there are no urwid constants that represent the mouse
        # events.
        if button == 4:  # Scroll up event
            super().keypress(size, 'up')
        elif button == 5:  # Scroll down event
            super().keypress(size, 'down')


class HistoryWindow(urwid.Frame):
    """
    This window composes the HistoryBox and EditorWidget in a horizontal split.
    By default the first focus is given to the history box.

    :param parent: Reference to the TUI object.
    """
    def __init__(self, parent: App) -> None:
        self.parent = parent
        self.editor_widget = EditorWidget(parent)
        self.editor = urwid.LineBox(self.editor_widget)
        self.history = HistoryBox(parent)
        self.body = urwid.Pile([('weight', 80, self.history),
                                ('weight', 20, self.editor)])
        super().__init__(self.body)
        urwid.connect_signal(self.parent, UPDATE_MSG, self.cb_add_to_history)

    def cb_add_to_history(self, msg: str, level: Optional[str] = None) -> None:
        """
        Appends a message to the history box

        :param msg:
            The message to be appended to the history box.
        :param level:
            The log level of the message, if it is a log message.
        """
        formatted = []
        if level:
            msg = f'[{level}]: {msg}'
            formatted.append((level, msg))
        else:
            lexer = lexers.JsonLexer()  # pylint: disable=no-member
            for token in lexer.get_tokens(msg):
                formatted.append(token)
        self.history.add_to_history(formatted)


class Window(urwid.Frame):
    """
    This window is the top most widget of the TUI and will contain other
    windows. Each child of this widget is responsible for displaying a specific
    functionality.

    :param parent: Reference to the TUI object.
    """
    def __init__(self, parent: App) -> None:
        self.parent = parent
        footer = StatusBar()
        body = HistoryWindow(parent)
        super().__init__(body, footer=footer)


class TUILogHandler(Handler):
    """
    This handler routes all the log messages to the TUI screen.
    It is installed to the root logger to so that the log message from all
    libraries begin used is routed to the screen.

    :param tui: Reference to the TUI object.
    """
    def __init__(self, tui: App) -> None:
        super().__init__()
        self.tui = tui

    def emit(self, record: LogRecord) -> None:
        """
        Emits a record to the TUI screen.

        Appends the log message to the TUI screen
        """
        level = record.levelname
        msg = record.getMessage()
        self.tui.add_to_history(msg, level)


def main() -> None:
    """
    Driver of the whole script, parses arguments, initialize the TUI and
    the logger.
    """
    parser = argparse.ArgumentParser(description='QMP TUI')
    parser.add_argument('qmp_server', help='Address of the QMP server. '
                        'Format <UNIX socket path | TCP addr:port>')
    parser.add_argument('--num-retries', type=int, default=10,
                        help='Number of times to reconnect before giving up.')
    parser.add_argument('--retry-delay', type=int,
                        help='Time(s) to wait before next retry. '
                        'Default action is to wait 2s between each retry.')
    parser.add_argument('--log-file', help='The Log file name')
    parser.add_argument('--log-level', default='WARNING',
                        help='Log level <CRITICAL|ERROR|WARNING|INFO|DEBUG|>')
    parser.add_argument('--asyncio-debug', action='store_true',
                        help='Enable debug mode for asyncio loop. '
                        'Generates lot of output, makes TUI unusable when '
                        'logs are logged in the TUI. '
                        'Use only when logging to a file.')
    args = parser.parse_args()

    try:
        address = QEMUMonitorProtocol.parse_address(args.qmp_server)
    except QMPBadPortError as err:
        parser.error(str(err))

    app = App(address, args.num_retries, args.retry_delay)

    root_logger = logging.getLogger()
    root_logger.setLevel(logging.getLevelName(args.log_level))

    if args.log_file:
        root_logger.addHandler(logging.FileHandler(args.log_file))
    else:
        root_logger.addHandler(TUILogHandler(app))

    app.run(args.asyncio_debug)


if __name__ == '__main__':
    main()
