# 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)

# TODO remove header classes and use the corresponding class instead
def generate_header_classes(install_dir):
    for cls in of_g.standard_class_order:
        if not cls.endswith("_header") or cls in ["of_header", "of_bsn_header", "of_nicira_header"]:
            continue
        with template_utils.open_output(install_dir, "loci/src/%s.c" % cls) as out:
            util.render_template(out, "class.c",
                push_wire_types_data=None,
                parse_wire_types_data=None)
            # Append legacy generated code
            c_code_gen.gen_new_function_definitions(out, cls)
            c_code_gen.gen_accessor_definitions(out, cls)

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)
    c_code_gen.gen_generics(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)
    c_type_maps.gen_extra_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 = {}

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

        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_action:
            wire_length_set = 'of_tlv16_wire_length_set'
            wire_length_get = 'of_tlv16_wire_length_get'
            wire_type_get = 'of_action_wire_object_id_get'
        elif uclass.is_instanceof('of_bsn_vport'):
            wire_length_set = 'of_tlv16_wire_length_set'
            wire_length_get = 'of_tlv16_wire_length_get'
            wire_type_get = 'of_bsn_vport_wire_object_id_get'
        elif uclass.is_action_id:
            wire_length_set = 'of_tlv16_wire_length_set'
            wire_length_get = 'of_tlv16_wire_length_get'
            wire_type_get = 'of_action_id_wire_object_id_get'
        elif uclass.is_instruction:
            wire_length_set = 'of_tlv16_wire_length_set'
            wire_length_get = 'of_tlv16_wire_length_get'
            wire_type_get = 'of_instruction_wire_object_id_get'
        elif uclass.is_instanceof('of_instruction_id'):
            wire_length_set = 'of_tlv16_wire_length_set'
            wire_length_get = 'of_tlv16_wire_length_get'
            wire_type_get = 'of_instruction_id_wire_object_id_get'
        elif uclass.is_instanceof('of_queue_prop'):
            wire_length_set = 'of_tlv16_wire_length_set'
            wire_length_get = 'of_tlv16_wire_length_get'
            wire_type_get = 'of_queue_prop_wire_object_id_get'
        elif uclass.is_instanceof('of_table_feature_prop'):
            wire_length_set = 'of_tlv16_wire_length_set'
            wire_length_get = 'of_tlv16_wire_length_get'
            wire_type_get = 'of_table_feature_prop_wire_object_id_get'
        elif uclass.is_instanceof('of_meter_band'):
            wire_length_set = 'of_tlv16_wire_length_set'
            wire_length_get = 'of_tlv16_wire_length_get'
            wire_type_get = 'of_meter_band_wire_object_id_get'
        elif uclass.is_instanceof('of_hello_elem'):
            wire_length_set = 'of_tlv16_wire_length_set'
            wire_length_get = 'of_tlv16_wire_length_get'
            wire_type_get = 'of_hello_elem_wire_object_id_get'
        elif uclass.is_instanceof('of_bsn_tlv'):
            wire_length_set = 'of_tlv16_wire_length_set'
            wire_length_get = 'of_tlv16_wire_length_get'
            wire_type_get = 'of_bsn_tlv_wire_object_id_get'
        elif uclass.is_oxm:
            wire_length_get = 'of_oxm_wire_length_get'
            wire_type_get = 'of_oxm_wire_object_id_get'
        elif uclass.name == "of_packet_queue":
            wire_length_get = 'of_packet_queue_wire_length_get'
            wire_length_set = 'of_packet_queue_wire_length_set'
        elif uclass.name == "of_meter_stats":
            wire_length_get = 'of_meter_stats_wire_length_get'
            wire_length_set = 'of_meter_stats_wire_length_set'
        elif uclass.name in ["of_group_desc_stats_entry", "of_group_stats_entry",
                "of_flow_stats_entry", "of_bucket", "of_table_features",
                "of_bsn_port_counter_stats_entry", "of_bsn_vlan_counter_stats_entry",
                "of_bsn_gentable_entry_desc_stats_entry", "of_bsn_gentable_entry_stats_entry",
                "of_bsn_gentable_desc_stats_entry", "of_bsn_vrf_counter_stats_entry"]:
            wire_length_get = "of_u16_len_wire_length_get"
            wire_length_set = "of_u16_len_wire_length_set"
        elif uclass.name == 'of_match_v3':
            wire_length_set = 'of_tlv16_wire_length_set'
            wire_length_get = 'of_tlv16_wire_length_get'
            wire_type_set = 'of_match_v3_push_wire_types'

        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))

    class_metadata.extend([
        ClassMetadata(
            name="of_action_header",
            wire_length_set='of_tlv16_wire_length_set',
            wire_length_get='of_tlv16_wire_length_get',
            wire_type_get='of_action_wire_object_id_get',
            wire_type_set='NULL'),
        ClassMetadata(
            name="of_action_id_header",
            wire_length_set='of_tlv16_wire_length_set',
            wire_length_get='of_tlv16_wire_length_get',
            wire_type_get='of_action_id_wire_object_id_get',
            wire_type_set='NULL'),
        ClassMetadata(
            name="of_bsn_vport_header",
            wire_length_set='of_tlv16_wire_length_set',
            wire_length_get='of_tlv16_wire_length_get',
            wire_type_get='of_bsn_vport_wire_object_id_get',
            wire_type_set='NULL'),
        ClassMetadata(
            name="of_instruction_header",
            wire_length_set='of_tlv16_wire_length_set',
            wire_length_get='of_tlv16_wire_length_get',
            wire_type_get='of_instruction_wire_object_id_get',
            wire_type_set='NULL'),
        ClassMetadata(
            name="of_instruction_id_header",
            wire_length_set='of_tlv16_wire_length_set',
            wire_length_get='of_tlv16_wire_length_get',
            wire_type_get='of_instruction_id_wire_object_id_get',
            wire_type_set='NULL'),
        ClassMetadata(
            name="of_queue_prop_header",
            wire_length_set='of_tlv16_wire_length_set',
            wire_length_get='of_tlv16_wire_length_get',
            wire_type_get='of_queue_prop_wire_object_id_get',
            wire_type_set='NULL'),
        ClassMetadata(
            name="of_table_feature_prop_header",
            wire_length_set='of_tlv16_wire_length_set',
            wire_length_get='of_tlv16_wire_length_get',
            wire_type_get='of_table_feature_prop_wire_object_id_get',
            wire_type_set='NULL'),
        ClassMetadata(
            name="of_meter_band_header",
            wire_length_set='of_tlv16_wire_length_set',
            wire_length_get='of_tlv16_wire_length_get',
            wire_type_get='of_meter_band_wire_object_id_get',
            wire_type_set='NULL'),
        ClassMetadata(
            name="of_hello_elem_header",
            wire_length_set='of_tlv16_wire_length_set',
            wire_length_get='of_tlv16_wire_length_get',
            wire_type_get='of_hello_elem_wire_object_id_get',
            wire_type_set='NULL'),
        ClassMetadata(
            name="of_bsn_tlv_header",
            wire_length_set='of_tlv16_wire_length_set',
            wire_length_get='of_tlv16_wire_length_get',
            wire_type_get='of_bsn_tlv_wire_object_id_get',
            wire_type_set='NULL'),
        ClassMetadata(
            name="of_oxm_header",
            wire_length_set='NULL',
            wire_length_get='of_oxm_wire_length_get',
            wire_type_get='of_oxm_wire_object_id_get',
            wire_type_set='NULL'),
    ])

    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)
