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

from collections import namedtuple

OFTypeData = namedtuple("OFTypeData", ["init", "pack", "unpack"])

# Map from LOXI type name to an object with templates for init, pack, and unpack
# Most types are defined using the convenience code below. This dict should
# only be used directly for special cases such as primitive types.
type_data_map = {
    'char': OFTypeData(
        init='0',
        pack='struct.pack("!B", %s)',
        unpack='%s.read("!B")[0]'),

    'uint8_t': OFTypeData(
        init='0',
        pack='struct.pack("!B", %s)',
        unpack='%s.read("!B")[0]'),

    'uint16_t': OFTypeData(
        init='0',
        pack='struct.pack("!H", %s)',
        unpack='%s.read("!H")[0]'),

    'uint32_t': OFTypeData(
        init='0',
        pack='struct.pack("!L", %s)',
        unpack='%s.read("!L")[0]'),

    'uint64_t': OFTypeData(
        init='0',
        pack='struct.pack("!Q", %s)',
        unpack='%s.read("!Q")[0]'),

    'of_port_no_t': OFTypeData(
        init='0',
        pack='util.pack_port_no(%s)',
        unpack='util.unpack_port_no(%s)'),

    'of_fm_cmd_t': OFTypeData(
        init='0',
        pack='util.pack_fm_cmd(%s)',
        unpack='util.unpack_fm_cmd(%s)'),

    'of_wc_bmap_t': OFTypeData(
        init='util.init_wc_bmap()',
        pack='util.pack_wc_bmap(%s)',
        unpack='util.unpack_wc_bmap(%s)'),

    'of_match_bmap_t': OFTypeData(
        init='util.init_match_bmap()',
        pack='util.pack_match_bmap(%s)',
        unpack='util.unpack_match_bmap(%s)'),

    'of_ipv4_t': OFTypeData(
        init='0',
        pack='struct.pack("!L", %s)',
        unpack='%s.read("!L")[0]'),

    'of_ipv6_t': OFTypeData(
        init="'\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'",
        pack='struct.pack("!16s", %s)',
        unpack="%s.read('!16s')[0]"),

    'of_mac_addr_t': OFTypeData(
        init='[0,0,0,0,0,0]',
        pack='struct.pack("!6B", *%s)',
        unpack="list(%s.read('!6B'))"),

    'of_octets_t': OFTypeData(
        init="''",
        pack='%s',
        unpack='str(%s.read_all())'),

    # HACK need the match_v3 length field
    'list(of_oxm_t)': OFTypeData(
        init='[]',
        pack='util.pack_list(%s)',
        unpack='oxm.unpack_list(%s.slice(_length-4))'),

    # TODO implement unpack
    'list(of_table_features_t)': OFTypeData(
        init='[]',
        pack='util.pack_list(%s)',
        unpack=None),

    # TODO implement unpack
    'list(of_action_id_t)': OFTypeData(
        init='[]',
        pack='util.pack_list(%s)',
        unpack=None),

    # TODO implement unpack
    'list(of_table_feature_prop_t)': OFTypeData(
        init='[]',
        pack='util.pack_list(%s)',
        unpack=None),
}

## Fixed length strings

# Map from class name to length
fixed_length_strings = {
    'of_port_name_t': 16,
    'of_table_name_t': 32,
    'of_serial_num_t': 32,
    'of_desc_str_t': 256,
}

for (cls, length) in fixed_length_strings.items():
    type_data_map[cls] = OFTypeData(
        init='""',
        pack='struct.pack("!%ds", %%s)' % length,
        unpack='%%s.read("!%ds")[0].rstrip("\\x00")' % length)

## Embedded structs

# Map from class name to Python class name
embedded_structs = {
    'of_match_t': 'common.match',
    'of_port_desc_t': 'common.port_desc',
    'of_meter_features_t': 'common.meter_features',
    'of_bsn_vport_q_in_q_t': 'common.bsn_vport_q_in_q',
}

for (cls, pyclass) in embedded_structs.items():
    type_data_map[cls] = OFTypeData(
        init='%s()' % pyclass,
        pack='%s.pack()',
        unpack='%s.unpack(%%s)' % pyclass)

## Variable element length lists

# Map from list class name to list deserializer
variable_elem_len_lists = {
    'list(of_action_t)': 'action.unpack_list',
    'list(of_bucket_t)': 'common.unpack_list_bucket',
    'list(of_flow_stats_entry_t)': 'common.unpack_list_flow_stats_entry',
    'list(of_group_desc_stats_entry_t)': 'common.unpack_list_group_desc_stats_entry',
    'list(of_group_stats_entry_t)': 'common.unpack_list_group_stats_entry',
    'list(of_hello_elem_t)': 'common.unpack_list_hello_elem',
    'list(of_instruction_t)': 'instruction.unpack_list',
    'list(of_meter_band_t)': 'meter_band.unpack_list',
    'list(of_meter_stats_t)': 'common.unpack_list_meter_stats',
    'list(of_packet_queue_t)': 'common.unpack_list_packet_queue',
    'list(of_queue_prop_t)': 'common.unpack_list_queue_prop',
}

for (cls, deserializer) in variable_elem_len_lists.items():
    type_data_map[cls] = OFTypeData(
        init='[]',
        pack='util.pack_list(%s)',
        unpack='%s(%%s)' % deserializer)

## Fixed element length lists

# Map from list class name to list element deserializer
fixed_elem_len_lists = {
    'list(of_bsn_interface_t)': 'common.bsn_interface.unpack',
    'list(of_bucket_counter_t)': 'common.bucket_counter.unpack',
    'list(of_meter_band_stats_t)': 'common.meter_band_stats.unpack',
    'list(of_port_desc_t)': 'common.port_desc.unpack',
    'list(of_port_stats_entry_t)': 'common.port_stats_entry.unpack',
    'list(of_queue_stats_entry_t)': 'common.queue_stats_entry.unpack',
    'list(of_table_stats_entry_t)': 'common.table_stats_entry.unpack',
    'list(of_uint32_t)': 'common.uint32.unpack',
    'list(of_uint8_t)': 'common.uint8.unpack',
}

for (cls, element_deserializer) in fixed_elem_len_lists.items():
    type_data_map[cls] = OFTypeData(
        init='[]',
        pack='util.pack_list(%s)',
        unpack='loxi.generic_util.unpack_list(%%s, %s)' % element_deserializer)

## Public interface

# Return an initializer expression for the given oftype
def gen_init_expr(oftype):
    type_data = type_data_map.get(oftype)
    if type_data and type_data.init:
        return type_data.init
    else:
        return "loxi.unimplemented('init %s')" % oftype

# Return a pack expression for the given oftype
#
# 'value_expr' is a string of Python code which will evaluate to
# the value to be packed.
def gen_pack_expr(oftype, value_expr):
    type_data = type_data_map.get(oftype)
    if type_data and type_data.pack:
        return type_data.pack % value_expr
    else:
        return "loxi.unimplemented('pack %s')" % oftype

# Return an unpack expression for the given oftype
#
# 'reader_expr' is a string of Python code which will evaluate to
# the OFReader instance used for deserialization.
def gen_unpack_expr(oftype, reader_expr):
    type_data = type_data_map.get(oftype)
    if type_data and type_data.unpack:
        return type_data.unpack % reader_expr
    else:
        return "loxi.unimplemented('unpack %s')" % oftype
