"""
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.aqmp import QMPError
from qemu.aqmp.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)
