# 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: {}".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
