"""
QOM Command abstractions.
"""
##
# Copyright John Snow 2020, for Red Hat, Inc.
# Copyright IBM, Corp. 2011
#
# Authors:
#  John Snow <jsnow@redhat.com>
#  Anthony Liguori <aliguori@amazon.com>
#
# This work is licensed under the terms of the GNU GPL, version 2 or later.
# See the COPYING file in the top-level directory.
#
# Based on ./scripts/qmp/qom-[set|get|tree|list]
##

import argparse
import os
import sys
from typing import (
    Any,
    Dict,
    List,
    Optional,
    Type,
    TypeVar,
)

from qemu.qmp import QMPError
from qemu.qmp.legacy import QEMUMonitorProtocol


class ObjectPropertyInfo:
    """
    Represents the return type from e.g. qom-list.
    """
    def __init__(self, name: str, type_: str,
                 description: Optional[str] = None,
                 default_value: Optional[object] = None):
        self.name = name
        self.type = type_
        self.description = description
        self.default_value = default_value

    @classmethod
    def make(cls, value: Dict[str, Any]) -> 'ObjectPropertyInfo':
        """
        Build an ObjectPropertyInfo from a Dict with an unknown shape.
        """
        assert value.keys() >= {'name', 'type'}
        assert value.keys() <= {'name', 'type', 'description', 'default-value'}
        return cls(value['name'], value['type'],
                   value.get('description'),
                   value.get('default-value'))

    @property
    def child(self) -> bool:
        """Is this property a child property?"""
        return self.type.startswith('child<')

    @property
    def link(self) -> bool:
        """Is this property a link property?"""
        return self.type.startswith('link<')


CommandT = TypeVar('CommandT', bound='QOMCommand')


class QOMCommand:
    """
    Represents a QOM sub-command.

    :param args: Parsed arguments, as returned from parser.parse_args.
    """
    name: str
    help: str

    def __init__(self, args: argparse.Namespace):
        if args.socket is None:
            raise QMPError("No QMP socket path or address given")
        self.qmp = QEMUMonitorProtocol(
            QEMUMonitorProtocol.parse_address(args.socket)
        )
        self.qmp.connect()

    @classmethod
    def register(cls, subparsers: Any) -> None:
        """
        Register this command with the argument parser.

        :param subparsers: argparse subparsers object, from "add_subparsers".
        """
        subparser = subparsers.add_parser(cls.name, help=cls.help,
                                          description=cls.help)
        cls.configure_parser(subparser)

    @classmethod
    def configure_parser(cls, parser: argparse.ArgumentParser) -> None:
        """
        Configure a parser with this command's arguments.

        :param parser: argparse parser or subparser object.
        """
        default_path = os.environ.get('QMP_SOCKET')
        parser.add_argument(
            '--socket', '-s',
            dest='socket',
            action='store',
            help='QMP socket path or address (addr:port).'
            ' May also be set via QMP_SOCKET environment variable.',
            default=default_path
        )
        parser.set_defaults(cmd_class=cls)

    @classmethod
    def add_path_prop_arg(cls, parser: argparse.ArgumentParser) -> None:
        """
        Add the <path>.<proptery> positional argument to this command.

        :param parser: The parser to add the argument to.
        """
        parser.add_argument(
            'path_prop',
            metavar='<path>.<property>',
            action='store',
            help="QOM path and property, separated by a period '.'"
        )

    def run(self) -> int:
        """
        Run this command.

        :return: 0 on success, 1 otherwise.
        """
        raise NotImplementedError

    def qom_list(self, path: str) -> List[ObjectPropertyInfo]:
        """
        :return: a strongly typed list from the 'qom-list' command.
        """
        rsp = self.qmp.command('qom-list', path=path)
        # qom-list returns List[ObjectPropertyInfo]
        assert isinstance(rsp, list)
        return [ObjectPropertyInfo.make(x) for x in rsp]

    @classmethod
    def command_runner(
            cls: Type[CommandT],
            args: argparse.Namespace
    ) -> int:
        """
        Run a fully-parsed subcommand, with error-handling for the CLI.

        :return: The return code from `run()`.
        """
        try:
            cmd = cls(args)
            return cmd.run()
        except QMPError as err:
            print(f"{type(err).__name__}: {err!s}", file=sys.stderr)
            return -1

    @classmethod
    def entry_point(cls) -> int:
        """
        Build this command's parser, parse arguments, and run the command.

        :return: `run`'s return code.
        """
        parser = argparse.ArgumentParser(description=cls.help)
        cls.configure_parser(parser)
        args = parser.parse_args()
        return cls.command_runner(args)
