#
# QAPI parser test harness
#
# Copyright (c) 2013 Red Hat Inc.
#
# Authors:
#  Markus Armbruster <armbru@redhat.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.
#

from __future__ import print_function
import sys
from qapi.common import QAPIError, QAPISchema, QAPISchemaVisitor


class QAPISchemaTestVisitor(QAPISchemaVisitor):

    def visit_module(self, name):
        print('module %s' % name)

    def visit_include(self, name, info):
        print('include %s' % name)

    def visit_enum_type(self, name, info, ifcond, members, prefix):
        print('enum %s' % name)
        if prefix:
            print('    prefix %s' % prefix)
        for m in members:
            print('    member %s' % m.name)
            self._print_if(m.ifcond, indent=8)
        self._print_if(ifcond)

    def visit_array_type(self, name, info, ifcond, element_type):
        if not info:
            return              # suppress built-in arrays
        print('array %s %s' % (name, element_type.name))
        self._print_if(ifcond)

    def visit_object_type(self, name, info, ifcond, base, members, variants,
                          features):
        print('object %s' % name)
        if base:
            print('    base %s' % base.name)
        for m in members:
            print('    member %s: %s optional=%s'
                  % (m.name, m.type.name, m.optional))
            self._print_if(m.ifcond, 8)
        self._print_variants(variants)
        self._print_if(ifcond)
        if features:
            for f in features:
                print('    feature %s' % f.name)
                self._print_if(f.ifcond, 8)

    def visit_alternate_type(self, name, info, ifcond, variants):
        print('alternate %s' % name)
        self._print_variants(variants)
        self._print_if(ifcond)

    def visit_command(self, name, info, ifcond, arg_type, ret_type, gen,
                      success_response, boxed, allow_oob, allow_preconfig):
        print('command %s %s -> %s'
              % (name, arg_type and arg_type.name,
                 ret_type and ret_type.name))
        print('   gen=%s success_response=%s boxed=%s oob=%s preconfig=%s'
              % (gen, success_response, boxed, allow_oob, allow_preconfig))
        self._print_if(ifcond)

    def visit_event(self, name, info, ifcond, arg_type, boxed):
        print('event %s %s' % (name, arg_type and arg_type.name))
        print('   boxed=%s' % boxed)
        self._print_if(ifcond)

    @staticmethod
    def _print_variants(variants):
        if variants:
            print('    tag %s' % variants.tag_member.name)
            for v in variants.variants:
                print('    case %s: %s' % (v.name, v.type.name))
                QAPISchemaTestVisitor._print_if(v.ifcond, indent=8)

    @staticmethod
    def _print_if(ifcond, indent=4):
        if ifcond:
            print('%sif %s' % (' ' * indent, ifcond))


try:
    schema = QAPISchema(sys.argv[1])
except QAPIError as err:
    print(err, file=sys.stderr)
    exit(1)

schema.visit(QAPISchemaTestVisitor())

for doc in schema.docs:
    if doc.symbol:
        print('doc symbol=%s' % doc.symbol)
    else:
        print('doc freeform')
    print('    body=\n%s' % doc.body.text)
    for arg, section in doc.args.items():
        print('    arg=%s\n%s' % (arg, section.text))
    for section in doc.sections:
        print('    section=%s\n%s' % (section.name, section.text))
