"""
QEMU development and testing utilities

This package provides a small handful of utilities for performing
various tasks not directly related to the launching of a VM.
"""

# Copyright (C) 2021 Red Hat Inc.
#
# Authors:
#  John Snow <jsnow@redhat.com>
#  Cleber Rosa <crosa@redhat.com>
#
# This work is licensed under the terms of the GNU GPL, version 2.  See
# the COPYING file in the top-level directory.
#

import os
import re
import shutil
from subprocess import CalledProcessError
import textwrap
from typing import Optional

# pylint: disable=import-error
from .accel import kvm_available, list_accel, tcg_available


__all__ = (
    'VerboseProcessError',
    'add_visual_margin',
    'get_info_usernet_hostfwd_port',
    'kvm_available',
    'list_accel',
    'tcg_available',
)


def get_info_usernet_hostfwd_port(info_usernet_output: str) -> Optional[int]:
    """
    Returns the port given to the hostfwd parameter via info usernet

    :param info_usernet_output: output generated by hmp command "info usernet"
    :return: the port number allocated by the hostfwd option
    """
    for line in info_usernet_output.split('\r\n'):
        regex = r'TCP.HOST_FORWARD.*127\.0\.0\.1\s+(\d+)\s+10\.'
        match = re.search(regex, line)
        if match is not None:
            return int(match[1])
    return None


# pylint: disable=too-many-arguments
def add_visual_margin(
        content: str = '',
        width: Optional[int] = None,
        name: Optional[str] = None,
        padding: int = 1,
        upper_left: str = '┏',
        lower_left: str = '┗',
        horizontal: str = '━',
        vertical: str = '┃',
) -> str:
    """
    Decorate and wrap some text with a visual decoration around it.

    This function assumes that the text decoration characters are single
    characters that display using a single monospace column.

    ┏━ Example ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
    ┃ This is what this function looks like with text content that's
    ┃ wrapped to 66 characters. The right-hand margin is left open to
    ┃ accommodate the occasional unicode character that might make
    ┃ predicting the total "visual" width of a line difficult. This
    ┃ provides a visual distinction that's good-enough, though.
    ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

    :param content: The text to wrap and decorate.
    :param width:
        The number of columns to use, including for the decoration
        itself. The default (None) uses the available width of the
        current terminal, or a fallback of 72 lines. A negative number
        subtracts a fixed-width from the default size. The default obeys
        the COLUMNS environment variable, if set.
    :param name: A label to apply to the upper-left of the box.
    :param padding: How many columns of padding to apply inside.
    :param upper_left: Upper-left single-width text decoration character.
    :param lower_left: Lower-left single-width text decoration character.
    :param horizontal: Horizontal single-width text decoration character.
    :param vertical: Vertical single-width text decoration character.
    """
    if width is None or width < 0:
        avail = shutil.get_terminal_size(fallback=(72, 24))[0]
        if width is None:
            _width = avail
        else:
            _width = avail + width
    else:
        _width = width

    prefix = vertical + (' ' * padding)

    def _bar(name: Optional[str], top: bool = True) -> str:
        ret = upper_left if top else lower_left
        if name is not None:
            ret += f"{horizontal} {name} "

        filler_len = _width - len(ret)
        ret += f"{horizontal * filler_len}"
        return ret

    def _wrap(line: str) -> str:
        return os.linesep.join(
            textwrap.wrap(
                line, width=_width - padding, initial_indent=prefix,
                subsequent_indent=prefix, replace_whitespace=False,
                drop_whitespace=True, break_on_hyphens=False)
        )

    return os.linesep.join((
        _bar(name, top=True),
        os.linesep.join(_wrap(line) for line in content.splitlines()),
        _bar(None, top=False),
    ))


class VerboseProcessError(CalledProcessError):
    """
    The same as CalledProcessError, but more verbose.

    This is useful for debugging failed calls during test executions.
    The return code, signal (if any), and terminal output will be displayed
    on unhandled exceptions.
    """
    def summary(self) -> str:
        """Return the normal CalledProcessError str() output."""
        return super().__str__()

    def __str__(self) -> str:
        lmargin = '  '
        width = -len(lmargin)
        sections = []

        # Does self.stdout contain both stdout and stderr?
        has_combined_output = self.stderr is None

        name = 'output' if has_combined_output else 'stdout'
        if self.stdout:
            sections.append(add_visual_margin(self.stdout, width, name))
        else:
            sections.append(f"{name}: N/A")

        if self.stderr:
            sections.append(add_visual_margin(self.stderr, width, 'stderr'))
        elif not has_combined_output:
            sections.append("stderr: N/A")

        return os.linesep.join((
            self.summary(),
            textwrap.indent(os.linesep.join(sections), prefix=lmargin),
        ))
