# Copyright 2013, Big Switch Networks, Inc.
#
# LoxiGen is licensed under the Eclipse Public License, version 1.0 (EPL), with
# the following special exception:
#
# LOXI Exception
#
# As a special exception to the terms of the EPL, you may distribute libraries
# generated by LoxiGen (LoxiGen Libraries) under the terms of your choice, provided
# that copyright and licensing notices generated by LoxiGen are not altered or removed
# from the LoxiGen Libraries and the notice provided below is (i) included in
# the LoxiGen Libraries, if distributed in source code form and (ii) included in any
# documentation for the LoxiGen Libraries, if distributed in binary form.
#
# Notice: "Copyright 2013, Big Switch Networks, Inc. This library was generated by the LoxiGen Compiler."
#
# You may not use this file except in compliance with the EPL or LOXI Exception. You may obtain
# a copy of the EPL at:
#
# http://www.eclipse.org/legal/epl-v10.html
#
# 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
# EPL for the specific language governing permissions and limitations
# under the EPL.

"""
Code generation

These functions extract data from the IR and render templates with it.
"""

from collections import namedtuple
from itertools import groupby
from StringIO import StringIO
import template_utils
from generic_utils import chunks
import loxi_globals
import loxi_ir.ir as ir
import util
import c_code_gen
import c_gen.of_g_legacy as of_g
import c_gen.type_maps as type_maps
import c_gen.c_type_maps as c_type_maps
import loxi_utils.loxi_utils as loxi_utils
import c_gen.loxi_utils_legacy as loxi_utils_legacy

CLASS_CHUNK_SIZE = 32

PushWireTypesData = namedtuple('PushWireTypesData',
    ['class_name', 'versioned_type_members'])
PushWireTypesMember = namedtuple('PushWireTypesMember',
    ['name', 'offset', 'length', 'value'])

def push_wire_types_data(uclass):
    if uclass.virtual or not uclass.has_type_members:
        return None

    # Generate a dict of version -> list of PushWireTypesMember
    type_members_by_version = {}
    for version, ofclass in sorted(uclass.version_classes.items()):
        pwtms = []
        for m in ofclass.members:
            if isinstance(m, ir.OFTypeMember):
                if m.name == "version" and m.value == version.wire_version:
                    # Special case for version
                    pwtms.append(PushWireTypesMember(m.name, m.offset, m.length, "obj->version"))
                else:
                    pwtms.append(PushWireTypesMember(m.name, m.offset, m.length, hex(m.value)))
        type_members_by_version[version] = pwtms

    # Merge versions with identical type members
    all_versions = sorted(type_members_by_version.keys())
    versioned_type_members = []
    for pwtms, versions in groupby(all_versions, type_members_by_version.get):
        versioned_type_members.append((pwtms, list(versions)))

    return PushWireTypesData(
        class_name=uclass.name,
        versioned_type_members=versioned_type_members)

ParseWireTypesData = namedtuple('ParseWireTypesData',
    ['class_name', 'versioned'])
ParseWireTypesVersion = namedtuple('ParseWireTypesVersion',
    ['discriminator', 'subclasses'])
ParseWireTypesSubclass = namedtuple('ParseWireTypesSubclass',
    ['class_name', 'value', 'virtual'])

def parse_wire_types_data(uclass):
    if not uclass.virtual:
        return None

    # Generate a dict of version -> ParseWireTypesVersion
    versioned = {}
    for version, ofclass in sorted(uclass.version_classes.items()):
        discriminator = ofclass.discriminator
        subclasses = [ParseWireTypesSubclass(class_name=subclass.name,
                                             value=subclass.member_by_name(discriminator.name).value,
                                             virtual=subclass.virtual)
                      for subclass in ofclass.protocol.classes if subclass.superclass and subclass.superclass.name == ofclass.name]

        subclasses.sort(key=lambda x: x.value)
        versioned[version] = ParseWireTypesVersion(discriminator=discriminator,
                                                   subclasses=subclasses)

    return ParseWireTypesData(class_name=uclass.name,
                              versioned=sorted(versioned.items()))

# Output multiple LOCI classes into each C file. This reduces the overhead of
# parsing header files, which takes longer than compiling the actual code
# for many classes. It also reduces the compiled code size.
def generate_classes(install_dir):
    for i, chunk in enumerate(chunks(loxi_globals.unified.classes, CLASS_CHUNK_SIZE)):
        with template_utils.open_output(install_dir, "loci/src/class%02d.c" % i) as out:
            for uclass in chunk:
                util.render_template(out, "class.c",
                    push_wire_types_data=push_wire_types_data(uclass),
                    parse_wire_types_data=parse_wire_types_data(uclass))
                # Append legacy generated code
                c_code_gen.gen_new_function_definitions(out, uclass.name)
                c_code_gen.gen_accessor_definitions(out, uclass.name)

def generate_classes_header(install_dir):
    # Collect legacy code
    tmp = StringIO()
    c_code_gen.gen_struct_typedefs(tmp)
    c_code_gen.gen_new_function_declarations(tmp)
    c_code_gen.gen_accessor_declarations(tmp)

    with template_utils.open_output(install_dir, "loci/inc/loci/loci_classes.h") as out:
        util.render_template(out, "loci_classes.h",
            legacy_code=tmp.getvalue())

def generate_lists(install_dir):
    # Collect all the lists in use
    list_oftypes = set()
    for uclass in loxi_globals.unified.classes:
        for ofclass in uclass.version_classes.values():
            for m in ofclass.members:
                if isinstance(m, ir.OFDataMember) and \
                        loxi_utils.oftype_is_list(m.oftype):
                    list_oftypes.add(m.oftype)

    for oftype in sorted(list(list_oftypes)):
        cls, e_cls = loxi_utils_legacy.list_name_extract(oftype)
        e_cls = e_cls[:-2]
        e_uclass = loxi_globals.unified.class_by_name(e_cls)
        with template_utils.open_output(install_dir, "loci/src/%s.c" % cls) as out:
            util.render_template(out, "list.c", cls=cls, e_cls=e_cls, e_uclass=e_uclass,
                                 wire_length_get=class_metadata_dict[e_cls].wire_length_get)
            # Append legacy generated code
            c_code_gen.gen_new_function_definitions(out, cls)

def generate_strings(install_dir):
    object_id_strs = []
    object_id_strs.append("of_object")
    object_id_strs.extend(of_g.ordered_messages)
    object_id_strs.extend(of_g.ordered_non_messages)
    object_id_strs.extend(of_g.ordered_list_objects)
    object_id_strs.extend(of_g.ordered_pseudo_objects)
    object_id_strs.append("of_unknown_object")

    with template_utils.open_output(install_dir, "loci/src/loci_strings.c") as out:
        util.render_template(out, "loci_strings.c", object_id_strs=object_id_strs)

def generate_init_map(install_dir):
    with template_utils.open_output(install_dir, "loci/src/loci_init_map.c") as out:
        util.render_template(out, "loci_init_map.c", classes=of_g.standard_class_order)

def generate_type_maps(install_dir):
    # Collect legacy code
    tmp = StringIO()
    c_type_maps.gen_length_array(tmp)

    with template_utils.open_output(install_dir, "loci/src/of_type_maps.c") as out:
        util.render_template(out, "of_type_maps.c", legacy_code=tmp.getvalue())

ClassMetadata = namedtuple('ClassMetadata',
    ['name', 'wire_length_get', 'wire_length_set', 'wire_type_get', 'wire_type_set'])

class_metadata = []
class_metadata_dict = {}

# These classes have handwritten C code to get/set their length fields
# See templates/of_type_maps.c
special_length_classes = set([
    'of_packet_queue', 'of_meter_stats', 'of_port_desc',
    'of_port_stats_entry', 'of_queue_stats_entry',
    'of_queue_desc',
])

def build_class_metadata():
    for uclass in loxi_globals.unified.classes:
        wire_length_get = 'NULL'
        wire_length_set = 'NULL'
        wire_type_get = 'NULL'
        wire_type_set = 'NULL'

        if uclass and not uclass.virtual and uclass.has_type_members:
            wire_type_set = '%s_push_wire_types' % uclass.name

        root = uclass.inheritance_root()
        if root and root.name != 'of_header':
            wire_type_get = root.name + '_wire_object_id_get'

        if uclass.is_message:
            wire_length_get = 'of_object_message_wire_length_get'
            wire_length_set = 'of_object_message_wire_length_set'
        elif uclass.is_oxm:
            wire_length_get = 'of_oxm_wire_length_get'
        elif uclass.name in special_length_classes:
            wire_length_get = '%s_wire_length_get' % uclass.name
            wire_length_set = '%s_wire_length_set' % uclass.name
        elif loxi_utils_legacy.class_is_tlv16(uclass.name):
            wire_length_set = 'of_tlv16_wire_length_set'
            wire_length_get = 'of_tlv16_wire_length_get'
        elif loxi_utils_legacy.class_is_u16_len(uclass.name):
            wire_length_get = "of_u16_len_wire_length_get"
            wire_length_set = "of_u16_len_wire_length_set"

        class_metadata.append(ClassMetadata(
            name=uclass.name,
            wire_length_get=wire_length_get,
            wire_length_set=wire_length_set,
            wire_type_get=wire_type_get,
            wire_type_set=wire_type_set))

    for metadata in class_metadata:
        class_metadata_dict[metadata.name] = metadata

def generate_class_metadata(install_dir):
    with template_utils.open_output(install_dir, "loci/inc/loci/loci_class_metadata.h") as out:
        util.render_template(out, "loci_class_metadata.h")

    with template_utils.open_output(install_dir, "loci/src/loci_class_metadata.c") as out:
        util.render_template(out, "loci_class_metadata.c", class_metadata=class_metadata)
