## List of mixed data types
#
# This is a list of data types which require special treatment
# because the underlying datatype has changed between versions.
# The main example is port which went from 16 to 32 bits.  We
# define per-version accessors for these types and those are
# used in place of the normal ones.
#
# The wire protocol number is used to identify versions.  For now,
# the value is the name of the type to use for that version
#
# This is the map between the external type (like of_port_no_t)
# which is used by customers of this code and the internal
# datatypes (like uint16_t) that appear on the wire for a
# particular version.
#
from collections import namedtuple
import logging

import loxi_front_end.frontend_ir as fe
import loxi_ir.ir

ofp_constants = dict(
    OF_MAX_TABLE_NAME_LEN = 32,
    OF_MAX_PORT_NAME_LEN  = 16,
    OF_ETH_ALEN = 6,
    OF_DESC_STR_LEN   = 256,
    OF_SERIAL_NUM_LEN = 32
)


of_mixed_types = dict(
    of_port_no_t = {
        1: "uint16_t",
        2: "uint32_t",
        3: "uint32_t",
        4: "uint32_t",
        5: "uint32_t",
        "short_name":"port_no"
        },
    of_port_desc_t = {
        1: "of_port_desc_t",
        2: "of_port_desc_t",
        3: "of_port_desc_t",
        4: "of_port_desc_t",
        5: "of_port_desc_t",
        "short_name":"port_desc"
        },
    of_bsn_vport_t = {
        1: "of_bsn_vport_t",
        2: "of_bsn_vport_t",
        3: "of_bsn_vport_t",
        4: "of_bsn_vport_t",
        5: "of_bsn_vport_t",
        "short_name":"bsn_vport"
        },
    of_fm_cmd_t = { # Flow mod command went from u16 to u8
        1: "uint16_t",
        2: "uint8_t",
        3: "uint8_t",
        4: "uint8_t",
        5: "uint8_t",
        "short_name":"fm_cmd"
        },
    of_wc_bmap_t = { # Wildcard bitmap
        1: "uint32_t",
        2: "uint32_t",
        3: "uint64_t",
        4: "uint64_t",
        5: "uint64_t",
        "short_name":"wc_bmap"
        },
    of_match_bmap_t = { # Match bitmap
        1: "uint32_t",
        2: "uint32_t",
        3: "uint64_t",
        4: "uint64_t",
        5: "uint64_t",
        "short_name":"match_bmap"
        },
    of_match_t = { # Match object
        1: "of_match_v1_t",
        2: "of_match_v2_t",
        3: "of_match_v3_t",
        4: "of_match_v3_t",  # Currently uses same match as 1.2 (v3).
        5: "of_match_v3_t",  # Currently uses same match as 1.2 (v3).
        "short_name":"match"
        },
)

## basic lengths
of_base_lengths = dict(
    char     = (1, True),
    uint8_t  = (1, True),
    uint16_t = (2, True),
    uint32_t = (4, True),
    uint64_t = (8, True),
    of_mac_addr_t = (6, True),
    of_ipv4_t = (4, True),
    of_ipv6_t = (16, True),
    of_port_name_t = (ofp_constants["OF_MAX_PORT_NAME_LEN"], True),
    of_table_name_t = (ofp_constants["OF_MAX_TABLE_NAME_LEN"], True),
    of_desc_str_t = (ofp_constants["OF_DESC_STR_LEN"], True),
    of_serial_num_t = (ofp_constants["OF_SERIAL_NUM_LEN"], True),
    of_str64_t = (64, True),
    of_match_v1_t = (40, True),
    of_match_v2_t = (88, True),
    of_match_v3_t = (8, False),
    of_octets_t = (0, False),
    of_bitmap_128_t = (16, True),
    of_checksum_128_t = (16, True),
    of_bitmap_512_t = (64, True),
)

def type_dec_to_count_base(m_type):
    """
    Resolve a type declaration like uint8_t[4] to a count (4) and base_type
    (uint8_t)

    @param m_type The string type declaration to process
    """
    count = 1
    chk_ar = m_type.split('[')
    if len(chk_ar) > 1:
        count_str = chk_ar[1].split(']')[0]
        if count_str in ofp_constants:
            count = ofp_constants[count_str]
        else:
            count = int(count_str)
        base_type = chk_ar[0]
    else:
        base_type = m_type
    return count, base_type


LengthInfo = namedtuple("LengthInfo", ("offset", "base_length", "is_fixed_length"))

def calc_lengths(version, fe_class, existing_classes, existing_enums):
    offset_fixed = True
    offset = 0

    member_infos = {}
    for member in fe_class.members:
        member_offset = offset if offset_fixed else None

        if isinstance(member, fe.OFPadMember):
            member_base_length = member.length
            member_fixed_length = True
        else:
            m_type = member.oftype
            name = member.name

            member_base_length = 0
            if m_type.find("list(") == 0:
                member_fixed_length = False
            elif m_type.find("struct") == 0:
                raise Exception("Error: recursive struct found: {}, {}"
                                    .format(fe_class.name, name))
            elif m_type == "octets":
                member_fixed_length = False
            else:
                member_base_length, member_fixed_length = member_length(version, fe_class, member, existing_classes, existing_enums)

        if not member_fixed_length:
            offset_fixed = False

        member_infos[member] = LengthInfo(member_offset, member_base_length,
                member_fixed_length)
        offset += member_base_length

    base_length = offset
    fixed_length = offset_fixed if not fe_class.virtual else False
    return (base_length, fixed_length, member_infos)

def member_length(version, fe_class, fe_member, existing_classes, existing_enums):
    """
    return the length of an ir member.

    @return tuple (base_length, length_fixed)
    """
    count, base_type = type_dec_to_count_base(fe_member.oftype)

    if base_type in of_mixed_types:
        base_type = of_mixed_types[base_type][version.wire_version]

    base_class = base_type[:-2]
    if base_class in existing_classes:
        member_ir_class = existing_classes[base_class]
        bytes = member_ir_class.base_length
        length_fixed = member_ir_class.is_fixed_length
        if member_ir_class.has_external_alignment:
            bytes = (bytes + 7) & ~7
    else:
        if base_type in existing_enums:
            enum = existing_enums[base_type]
            base_type = enum.wire_type

        if base_type in of_base_lengths:
            bytes, length_fixed = of_base_lengths[base_type]
        else:
            raise Exception("Unknown type for {}.{}: {}".format(fe_class.name, fe_member.name, base_type))

    return (count * bytes), length_fixed
