# 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 itertools import chain
import logging
import re
import sys

from collections import namedtuple, OrderedDict
from generic_utils import find, memoize, OrderedSet
from loxi_ir import ir_offset

logger = logging.getLogger(__name__)

# This module is intended to be imported like this: from loxi_ir import *
# All public names are prefixed with 'OF'.
__all__ = [
    'OFVersion',
    'OFProtocol',
    'OFClass',
    'OFUnifiedClass',
    'OFDataMember',
    'OFTypeMember',
    'OFDiscriminatorMember',
    'OFLengthMember',
    'OFFieldLengthMember',
    'OFPadMember',
    'OFEnum',
    'OFEnumEntry'
]

"""
One version of the OpenFlow protocol
@param version Official dotted version number (e.g., "1.0", "1.3")
@param wire_version Integer wire version (1 for 1.0, 4 for 1.3)
"""
class OFVersion(namedtuple("OFVersion", ("version", "wire_version"))):
    @property
    @memoize
    def constant(self):
        """ return this version as an uppercase string suitable
            for use as a c constant, e.g., "VERSION_1_3"
        """
        return self.constant_version(prefix="VERSION_")

    @property
    @memoize
    def short_constant(self):
        """ return this version as an uppercase string suitable
            for use as a c constant, e.g., "OF_"
        """
        return self.constant_version(prefix="OF_")

    def constant_version(self, prefix="VERSION_"):
        return prefix + self.version.replace(".", "_")

    def __repr__(self):
        return "OFVersion(%s)" % self.version

    def __str__(self):
        return self.version

    def __cmp__(self, other):
        return cmp(self.wire_version, other.wire_version)

"""
One version of the OpenFlow protocol

Combination of multiple OFInput objects.

@param wire_version
@param classes List of OFClass objects
@param enums List of Enum objects
"""
class OFProtocol(namedtuple('OFProtocol', ['version', 'classes', 'enums'])):
    def __init__(self, version, classes, enums):
        super(OFProtocol, self).__init__(self, version, classes, enums)
        assert version is None or isinstance(version, OFVersion)

    def class_by_name(self, name):
        return find(lambda ofclass: ofclass.name == name, self.classes)

    def enum_by_name(self, name):
        return find(lambda enum: enum.name == name, self.enums)

"""
An OpenFlow class

All compound objects like messages, actions, instructions, etc are
uniformly represented by this class.

The members are in the same order as on the wire.

@param name
@param superclass_name of this classes' super class
@param members List of *Member objects
@param params optional dictionary of parameters
"""
class OFClass(namedtuple('OFClass', ['name', 'superclass', 'members', 'virtual', 'params', 'is_fixed_length', 'base_length'])):
    def __init__(self, *a, **kw):
        super(OFClass, self).__init__(self, *a, **kw)
        # Back reference will be added by assignment
        self.protocol = None

    def member_by_name(self, name):
        return find(lambda m: hasattr(m, "name") and m.name == name, self.members)

    @property
    def discriminator(self):
        return find(lambda m: type(m) == OFDiscriminatorMember, self.members)

    def is_instanceof(self, super_class_name):
        if self.name == super_class_name:
            return True
        elif self.superclass is None:
            return False
        else:
            return self.superclass.is_instanceof(super_class_name)

    def is_subclassof(self, super_class_name):
        return self.name != super_class_name and self.is_instanceof(super_class_name)

    @property
    def is_message(self):
        return self.is_instanceof("of_header")

    @property
    def is_oxm(self):
        return self.is_instanceof("of_oxm")

    @property
    def is_action(self):
        return self.is_instanceof("of_action")

    @property
    def is_action_id(self):
        return self.is_instanceof("of_action_id")

    @property
    def is_instruction(self):
        return self.is_instanceof("of_instruction")

    def __hash__(self):
        return hash((self.name, self.protocol.wire_version if self.protocol else None))

    @property
    def length(self):
        if self.is_fixed_length:
            return self.base_length
        else:
            raise Exception("Not a fixed length class: {}".format(self.name))

""" one class unified across openflow versions. Keeps around a map version->versioned_class """
class OFUnifiedClass(OFClass):
    def __new__(cls, version_classes, *a, **kw):
        return super(OFUnifiedClass, cls).__new__(cls, *a, **kw)

    def __init__(self, version_classes, *a, **kw):
        super(OFUnifiedClass, self).__init__(*a, **kw)
        self.version_classes = version_classes

    def class_by_version(version):
        return self.version_classes[version]



""" A mixin for member classes. Keeps around the back reference of_class (for assignment by
    build_protocol, and additional methods shared across Members. """
class MemberMixin(object):
    def __init__(self, *a, **kw):
        super(MemberMixin, self).__init__(*a, **kw)
        # Back reference will be added by assignment in build_protocol below
        self.of_class = None

    @property
    def length(self):
        if self.is_fixed_length:
            return self.base_length
        else:
            raise Exception("Not a fixed length member: {}.{} [{}]".format(
                self.of_class.name,
                self.name if hasattr("self", name) else "(unnnamed)",
                type(self).__name__))

"""
Normal field

@param name
@param oftype C-like type string

Example: packet_in.buffer_id
"""
class OFDataMember(namedtuple('OFDataMember', ['name', 'oftype', 'is_fixed_length', 'base_length', 'offset']), MemberMixin):
    pass

"""
Field that declares that this is an abstract super-class and
that the sub classes will be discriminated based on this field.
E.g., 'type' is the discriminator member of the abstract superclass
of_action.

@param name
"""
class OFDiscriminatorMember (namedtuple('OFDiscriminatorMember', ['name', 'oftype', 'is_fixed_length', 'base_length', 'offset']), MemberMixin):
    pass

"""
Field used to determine the type of an OpenFlow object

@param name
@param oftype C-like type string
@param value Fixed type value

Example: packet_in.type, flow_add._command
"""
class OFTypeMember (namedtuple('OFTypeMember', ['name', 'oftype', 'value', 'is_fixed_length', 'base_length', 'offset']), MemberMixin):
    pass

"""
Field with the length of the containing object

@param name
@param oftype C-like type string

Example: packet_in.length, action_output.len
"""
class OFLengthMember (namedtuple('OFLengthMember', ['name', 'oftype', 'is_fixed_length', 'base_length', 'offset']), MemberMixin):
    pass

"""
Field with the length of another field in the containing object

@param name
@param oftype C-like type string
@param field_name Peer field whose length this field contains

Example: packet_out.actions_len (only usage)
"""
class OFFieldLengthMember (namedtuple('OFFieldLengthMember', ['name', 'oftype', 'field_name', 'is_fixed_length', 'base_length', 'offset']), MemberMixin):
    pass

"""
Zero-filled padding

@param length Length in bytes

Example: packet_in.pad
"""
class OFPadMember (namedtuple('OFPadMember', ['pad_length', 'is_fixed_length', 'base_length', 'offset']), MemberMixin):
    pass

"""
An OpenFlow enumeration

All values are Python ints.

@param name
@param entries List of OFEnumEntry objects in input order
@params dict of optional params. Currently defined:
       - wire_type: the low_level type of the enum values (uint8,...)
"""
class OFEnum(namedtuple('OFEnum', ['name', 'entries', 'params'])):
    def __init__(self, *a, **kw):
        super(OFEnum, self).__init__(*a, **kw)
        # Back reference will be added by assignment
        self.protocol = None

    @property
    def values(self):
        return [(e.name, e.value) for e in self.entries]

    @property
    def is_bitmask(self):
        return "bitmask" in self.params and self.params['bitmask']

    @property
    def wire_type(self):
        return self.params['wire_type'] if 'wire_type' in self.params else self.name

class OFEnumEntry(namedtuple('OFEnumEntry', ['name', 'value', 'params'])):
    def __init__(self, *a, **kw):
        super(OFEnumEntry, self).__init__(*a, **kw)
        # Back reference will be added by assignment
        self.enum = None

class RedefinedException(Exception):
    pass

class ClassNotFoundException(Exception):
    pass

class DependencyCycleException(Exception):
    pass

def build_protocol(version, ofinputs):
    name_frontend_classes = OrderedDict()
    name_frontend_enums = OrderedDict()

    for ofinput in ofinputs:
        for c in ofinput.classes:
            name = c.name
            if name in name_frontend_classes:
                raise RedefinedException("Error parsing {}. Class {} redefined (already defined in {})"
                        .format(ofinput.filename, name,
                            name_frontend_classes[name][1].filename))
            else:
                name_frontend_classes[name] = (c, ofinput)
        for e in ofinput.enums:
            name = e.name
            if name in name_frontend_enums:
                raise RedefinedException("Error parsing {}. Enum {} redefined (already defined in {})"
                        .format(ofinput.filename, name,
                            name_frontend_enums[name][1].filename))
            else:
                name_frontend_enums[name] = (e, ofinput)

    name_enums = {}
    for fe, _ in name_frontend_enums.values():
        entries = tuple(OFEnumEntry(name=e.name, value=e.value,
                        params=e.params) for e in fe.entries)
        enum = OFEnum(name=fe.name,
                      entries=entries,
                      params=fe.params)
        for e in entries:
            e.enum = enum
        name_enums[enum.name] = enum

    name_classes = OrderedDict()
    build_touch_classes = OrderedSet()

    def convert_member_properties(props):
        return { name if name != "length" else "pad_length" : value for name, value in props.items() }

    def build_member(of_class, fe_member, length_info):
        ir_class = globals()[type(fe_member).__name__]
        member = ir_class(offset = length_info.offset,
                        base_length = length_info.base_length,
                        is_fixed_length=length_info.is_fixed_length,
                        **convert_member_properties(vars(fe_member)))
        member.of_class = of_class
        return member

    def build_class(name):
        if name in name_classes:
            return name_classes[name]
        if name in build_touch_classes:
            raise DependencyCycleException( "Dependency cycle: {}"
                    .format(" -> ".join(list(build_touch_classes) + [name])))
        if not name in name_frontend_classes:
            raise ClassNotFoundException("Class not found: {}".format(name))

        build_touch_classes.add(name)

        fe, _ = name_frontend_classes[name]

        superclass = build_class(fe.superclass) if fe.superclass else None

        # make sure members on which we depend are built first (for calc_length)
        for m in fe.members:
            if not hasattr(m, "oftype"):
                continue
            for m_name in re.sub(r'_t$', '', m.oftype), m.oftype:
                logger.debug("Checking {}".format(m_name))
                if m_name in name_frontend_classes:
                    build_class(m_name)

        base_length, is_fixed_length, member_lengths = \
           ir_offset.calc_lengths(version, fe, name_classes, name_enums)

        members = []
        c = OFClass(name=fe.name, superclass=superclass,
                members=members, virtual=fe.virtual, params=fe.params,
                is_fixed_length=is_fixed_length, base_length=base_length)

        members.extend( build_member(c, fe_member, member_lengths[fe_member])
                  for fe_member in fe.members)

        name_classes[name] = c
        build_touch_classes.remove(name)
        return c

    for name in sorted(name_frontend_classes.keys()):
        c = build_class(name)

    protocol = OFProtocol(version=version, classes=tuple(name_classes.values()), enums=tuple(name_enums.values()))
    for e in chain(protocol.classes, protocol.enums):
        e.protocol = protocol
    return protocol
