#!/usr/bin/env python3
#
# QMP command line tool
#
# Copyright IBM, Corp. 2011
#
# Authors:
#  Anthony Liguori <aliguori@us.ibm.com>
#
# This work is licensed under the terms of the GNU GPLv2 or later.
# See the COPYING file in the top-level directory.

import sys, os
from qmp import QEMUMonitorProtocol

def print_response(rsp, prefix=[]):
    if type(rsp) == list:
        i = 0
        for item in rsp:
            if prefix == []:
                prefix = ['item']
            print_response(item, prefix[:-1] + ['%s[%d]' % (prefix[-1], i)])
            i += 1
    elif type(rsp) == dict:
        for key in rsp.keys():
            print_response(rsp[key], prefix + [key])
    else:
        if len(prefix):
            print('%s: %s' % ('.'.join(prefix), rsp))
        else:
            print('%s' % (rsp))

def main(args):
    path = None

    # Use QMP_PATH if it's set
    if 'QMP_PATH' in os.environ:
        path = os.environ['QMP_PATH']

    while len(args):
        arg = args[0]

        if arg.startswith('--'):
            arg = arg[2:]
            if arg.find('=') == -1:
                value = True
            else:
                arg, value = arg.split('=', 1)

            if arg in ['path']:
                if type(value) == str:
                    path = value
            elif arg in ['help']:
                os.execlp('man', 'man', 'qmp')
            else:
                print('Unknown argument "%s"' % arg)

            args = args[1:]
        else:
            break

    if not path:
        print("QMP path isn't set, use --path=qmp-monitor-address or set QMP_PATH")
        return 1

    if len(args):
        command, args = args[0], args[1:]
    else:
        print('No command found')
        print('Usage: "qmp [--path=qmp-monitor-address] qmp-cmd arguments"')
        return 1

    if command in ['help']:
        os.execlp('man', 'man', 'qmp')

    srv = QEMUMonitorProtocol(path)
    srv.connect()

    def do_command(srv, cmd, **kwds):
        rsp = srv.cmd(cmd, kwds)
        if 'error' in rsp:
            raise Exception(rsp['error']['desc'])
        return rsp['return']

    commands = map(lambda x: x['name'], do_command(srv, 'query-commands'))

    srv.close()

    if command not in commands:
        fullcmd = 'qmp-%s' % command
        try:
            os.environ['QMP_PATH'] = path
            os.execvp(fullcmd, [fullcmd] + args)
        except OSError as exc:
            if exc.errno == 2:
                print('Command "%s" not found.' % (fullcmd))
                return 1
            raise
        return 0

    srv = QEMUMonitorProtocol(path)
    srv.connect()

    arguments = {}
    for arg in args:
        if not arg.startswith('--'):
            print('Unknown argument "%s"' % arg)
            return 1

        arg = arg[2:]
        if arg.find('=') == -1:
            value = True
        else:
            arg, value = arg.split('=', 1)

        if arg in ['help']:
            os.execlp('man', 'man', 'qmp-%s' % command)
            return 1

        arguments[arg] = value

    rsp = do_command(srv, command, **arguments)
    print_response(rsp)

if __name__ == '__main__':
    sys.exit(main(sys.argv[1:]))
