#
# QAPI introspection generator
#
# Copyright (C) 2015 Red Hat, Inc.
#
# Authors:
#  Markus Armbruster <armbru@redhat.com>
#
# This work is licensed under the terms of the GNU GPL, version 2.
# See the COPYING file in the top-level directory.

from qapi import *


# Caveman's json.dumps() replacement (we're stuck at Python 2.4)
# TODO try to use json.dumps() once we get unstuck
def to_json(obj, level=0):
    if obj is None:
        ret = 'null'
    elif isinstance(obj, str):
        ret = '"' + obj.replace('"', r'\"') + '"'
    elif isinstance(obj, list):
        elts = [to_json(elt, level + 1)
                for elt in obj]
        ret = '[' + ', '.join(elts) + ']'
    elif isinstance(obj, dict):
        elts = ['"%s": %s' % (key.replace('"', r'\"'),
                              to_json(obj[key], level + 1))
                for key in sorted(obj.keys())]
        ret = '{' + ', '.join(elts) + '}'
    else:
        assert False                # not implemented
    if level == 1:
        ret = '\n' + ret
    return ret


def to_c_string(string):
    return '"' + string.replace('\\', r'\\').replace('"', r'\"') + '"'


class QAPISchemaGenIntrospectVisitor(QAPISchemaVisitor):
    def __init__(self, unmask):
        self._unmask = unmask
        self.defn = None
        self.decl = None
        self._schema = None
        self._jsons = None
        self._used_types = None
        self._name_map = None

    def visit_begin(self, schema):
        self._schema = schema
        self._jsons = []
        self._used_types = []
        self._name_map = {}

    def visit_end(self):
        # visit the types that are actually used
        jsons = self._jsons
        self._jsons = []
        for typ in self._used_types:
            typ.visit(self)
        # generate C
        # TODO can generate awfully long lines
        jsons.extend(self._jsons)
        name = prefix + 'qmp_schema_json'
        self.decl = mcgen('''
extern const char %(c_name)s[];
''',
                          c_name=c_name(name))
        lines = to_json(jsons).split('\n')
        c_string = '\n    '.join([to_c_string(line) for line in lines])
        self.defn = mcgen('''
const char %(c_name)s[] = %(c_string)s;
''',
                          c_name=c_name(name),
                          c_string=c_string)
        self._schema = None
        self._jsons = None
        self._used_types = None
        self._name_map = None

    def visit_needed(self, entity):
        # Ignore types on first pass; visit_end() will pick up used types
        return not isinstance(entity, QAPISchemaType)

    def _name(self, name):
        if self._unmask:
            return name
        if name not in self._name_map:
            self._name_map[name] = '%d' % len(self._name_map)
        return self._name_map[name]

    def _use_type(self, typ):
        # Map the various integer types to plain int
        if typ.json_type() == 'int':
            typ = self._schema.lookup_type('int')
        elif (isinstance(typ, QAPISchemaArrayType) and
              typ.element_type.json_type() == 'int'):
            typ = self._schema.lookup_type('intList')
        # Add type to work queue if new
        if typ not in self._used_types:
            self._used_types.append(typ)
        # Clients should examine commands and events, not types.  Hide
        # type names to reduce the temptation.  Also saves a few
        # characters.
        if isinstance(typ, QAPISchemaBuiltinType):
            return typ.name
        if isinstance(typ, QAPISchemaArrayType):
            return '[' + self._use_type(typ.element_type) + ']'
        return self._name(typ.name)

    def _gen_json(self, name, mtype, obj):
        if mtype not in ('command', 'event', 'builtin', 'array'):
            name = self._name(name)
        obj['name'] = name
        obj['meta-type'] = mtype
        self._jsons.append(obj)

    def _gen_member(self, member):
        ret = {'name': member.name, 'type': self._use_type(member.type)}
        if member.optional:
            ret['default'] = None
        return ret

    def _gen_variants(self, tag_name, variants):
        return {'tag': tag_name,
                'variants': [self._gen_variant(v) for v in variants]}

    def _gen_variant(self, variant):
        return {'case': variant.name, 'type': self._use_type(variant.type)}

    def visit_builtin_type(self, name, info, json_type):
        self._gen_json(name, 'builtin', {'json-type': json_type})

    def visit_enum_type(self, name, info, values, prefix):
        self._gen_json(name, 'enum', {'values': values})

    def visit_array_type(self, name, info, element_type):
        element = self._use_type(element_type)
        self._gen_json('[' + element + ']', 'array', {'element-type': element})

    def visit_object_type_flat(self, name, info, members, variants):
        obj = {'members': [self._gen_member(m) for m in members]}
        if variants:
            obj.update(self._gen_variants(variants.tag_member.name,
                                          variants.variants))
        self._gen_json(name, 'object', obj)

    def visit_alternate_type(self, name, info, variants):
        self._gen_json(name, 'alternate',
                       {'members': [{'type': self._use_type(m.type)}
                                    for m in variants.variants]})

    def visit_command(self, name, info, arg_type, ret_type,
                      gen, success_response):
        arg_type = arg_type or self._schema.the_empty_object_type
        ret_type = ret_type or self._schema.the_empty_object_type
        self._gen_json(name, 'command',
                       {'arg-type': self._use_type(arg_type),
                        'ret-type': self._use_type(ret_type)})

    def visit_event(self, name, info, arg_type):
        arg_type = arg_type or self._schema.the_empty_object_type
        self._gen_json(name, 'event', {'arg-type': self._use_type(arg_type)})

# Debugging aid: unmask QAPI schema's type names
# We normally mask them, because they're not QMP wire ABI
opt_unmask = False

(input_file, output_dir, do_c, do_h, prefix, opts) = \
    parse_command_line("u", ["unmask-non-abi-names"])

for o, a in opts:
    if o in ("-u", "--unmask-non-abi-names"):
        opt_unmask = True

c_comment = '''
/*
 * QAPI/QMP schema introspection
 *
 * Copyright (C) 2015 Red Hat, Inc.
 *
 * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
 * See the COPYING.LIB file in the top-level directory.
 *
 */
'''
h_comment = '''
/*
 * QAPI/QMP schema introspection
 *
 * Copyright (C) 2015 Red Hat, Inc.
 *
 * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
 * See the COPYING.LIB file in the top-level directory.
 *
 */
'''

(fdef, fdecl) = open_output(output_dir, do_c, do_h, prefix,
                            'qmp-introspect.c', 'qmp-introspect.h',
                            c_comment, h_comment)

fdef.write(mcgen('''
#include "%(prefix)sqmp-introspect.h"

''',
                 prefix=prefix))

schema = QAPISchema(input_file)
gen = QAPISchemaGenIntrospectVisitor(opt_unmask)
schema.visit(gen)
fdef.write(gen.defn)
fdecl.write(gen.decl)

close_output(fdef, fdecl)
