#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements.  See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership.  The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License.  You may obtain a copy of the License at
#
#   http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied.  See the License for the
# specific language governing permissions and limitations
# under the License
#

"""
Generate C code from the router schema.
"""
from __future__ import unicode_literals
from __future__ import division
from __future__ import absolute_import
from __future__ import print_function

import re
from qpid_dispatch_internal.management.schema import EnumType
from qpid_dispatch_internal.management.qdrouter import QdSchema

copyright="""/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */


"""


class Generator(object):

    def __init__(self):
        self.schema = QdSchema()
        self.prefix = ['qd_schema']

        self.generate_enums()

    def header(self, name, text):
        with open(name+'.h', 'w') as f:
            f.write("#ifndef __%s_h__\n#define __%s_h__\n"%(name, name) + copyright + text + "\n#endif\n")

    def source(self, name, text):
        with open(name+'.c', 'w') as f:
            f.write(copyright + text)

    def identifier(self, name): return re.sub(r'\W','_', name)

    def underscore(self, names): return '_'.join([self.identifier(name) for name in names])

    def prefix_name(self, names): return self.underscore(self.prefix + names)

    def type_name(self, names): return self.prefix_name(names + ['t'])

    class EnumGenerator(object):
        def __init__(self, generator, entity, attribute):
            self.generator, self.entity, self.attribute = generator, entity, attribute
            self.tags = attribute.atype.tags
            self.type_name = generator.type_name([entity.short_name, attribute.name])
            self.array = self.generator.prefix_name([entity.short_name, attribute.name, 'names'])
            self.count = self.name('ENUM_COUNT')

        def name(self, tag):
            return self.generator.prefix_name([self.entity.short_name, self.attribute.name, tag]).upper()

        def decl(self):
            tags = self.tags + ['ENUM_COUNT']
            return "typedef enum {\n" + \
                ",\n".join(["    " + self.name(tag) for tag in tags]) + \
                "\n} %s;\n\n" % self.type_name + \
                "extern const char *%s[%s];\n\n" %  (self.array, self.count)

        def defn(self):
            return "const char *%s[%s] = {\n" % (self.array, self.count) + \
                ",\n".join('    "%s"'%(self.name(tag)) for tag in self.tags) + \
                "\n};\n\n"

    def generate_enums(self):
        enums = [self.EnumGenerator(self, entity, attribute)
                 for entity in self.schema.entity_types.values()
                 for attribute in entity.attributes.values()
                 if isinstance(attribute.atype, EnumType)]
        self.header('schema_enum', '\n'.join(e.decl() for e in enums))
        self.source('schema_enum', '#include "schema_enum.h"\n\n' + '\n'.join(e.defn() for e in enums))

if __name__ == '__main__':
    Generator()
