#
# Copyright 2018 the original author or authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# 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 License for the specific language governing permissions and
# limitations under the License.
#
import threading
import binascii
import grpc
import socket
import re
import structlog
import time
from twisted.internet import reactor
from twisted.internet.defer import inlineCallbacks, returnValue
from scapy.layers.l2 import Ether, Dot1Q
from transitions import Machine

from voltha_protos import openolt_pb2_grpc, openolt_pb2

from pyvoltha.adapters.extensions.alarms.onu.onu_discovery_alarm import OnuDiscoveryAlarm

from pyvoltha.common.utils.nethelpers import mac_str_to_tuple
from voltha_protos.openflow_13_pb2 import OFPPS_LIVE, OFPPF_FIBER, \
    OFPPS_LINK_DOWN, OFPPF_1GB_FD, \
    OFPC_GROUP_STATS, OFPC_PORT_STATS, OFPC_TABLE_STATS, OFPC_FLOW_STATS, \
    ofp_switch_features, ofp_port, ofp_port_stats, ofp_desc
from pyvoltha.common.utils.registry import registry
from voltha_protos.common_pb2 import AdminState, OperStatus, ConnectStatus
from voltha_protos.device_pb2 import Port, Device
from voltha_protos.inter_container_pb2 import SwitchCapability, PortCapability, \
    InterAdapterMessageType, InterAdapterOmciMessage
from voltha_protos.logical_device_pb2 import LogicalDevice, LogicalPort


class OpenoltDevice(object):
    """
    OpenoltDevice state machine:

        null ----> init ------> connected -----> up -----> down
                   ^ ^             |             ^         | |
                   | |             |             |         | |
                   | +-------------+             +---------+ |
                   |                                         |
                   +-----------------------------------------+
    """
    # pylint: disable=too-many-instance-attributes
    # pylint: disable=R0904
    states = [
        'state_null', 'state_init', 'state_connected', 'state_up', 'state_down'
    ]

    transitions = [{
        'trigger': 'go_state_init',
        'source': ['state_null', 'state_connected', 'state_down'],
        'dest': 'state_init',
        'before': 'do_state_init',
        'after': 'post_init'
    }, {
        'trigger': 'go_state_connected',
        'source': 'state_init',
        'dest': 'state_connected',
        'before': 'do_state_connected'
    }, {
        'trigger': 'go_state_up',
        'source': ['state_connected', 'state_down'],
        'dest': 'state_up',
        'before': 'do_state_up'
    }, {
        'trigger': 'go_state_down',
        'source': ['state_up'],
        'dest': 'state_down',
        'before': 'do_state_down',
        'after': 'post_down'
    }]

    def __init__(self, **kwargs):
        super(OpenoltDevice, self).__init__()

        self.core_proxy = kwargs['core_proxy']
        self.adapter_proxy = kwargs['adapter_proxy']
        self.device_num = kwargs['device_num']
        self.device = kwargs['device']
        self.onus = dict()  # int_id.onu_id -> OnuDevice()
        self.platform_class = kwargs['support_classes']['platform']
        self.resource_mgr_class = kwargs['support_classes']['resource_mgr']
        self.flow_mgr_class = kwargs['support_classes']['flow_mgr']
        self.alarm_mgr_class = kwargs['support_classes']['alarm_mgr']
        self.stats_mgr_class = kwargs['support_classes']['stats_mgr']
        self.bw_mgr_class = kwargs['support_classes']['bw_mgr']

        self.seen_discovery_indications = []
        self.onu_cache = dict()
        self.indication_retries = 0
        self.stub = None
        self.connected = False
        is_reconciliation = kwargs.get('reconciliation', False)
        self.device_id = self.device.id
        self.host_and_port = self.device.host_and_port
        self.extra_args = self.device.extra_args
        self.device_info = None
        self.log = structlog.get_logger(id=self.device_id,
                                        ip=self.host_and_port)

        self.log.info('openolt-device-init')

        # default device id and device serial number. If device_info provides better results, they will be updated
        self.dpid = kwargs.get('dp_id')
        self.serial_number = self.host_and_port  # FIXME

        # Device already set in the event of reconciliation
        if not is_reconciliation:
            self.log.info('updating-device')
            # It is a new device
            # Update device
            self.device.root = True
            self.device.connect_status = ConnectStatus.UNREACHABLE
            self.device.oper_status = OperStatus.ACTIVATING

        # Initialize the OLT state machine
        self.machine = Machine(model=self,
                               states=OpenoltDevice.states,
                               transitions=OpenoltDevice.transitions,
                               send_event=True,
                               initial='state_null')
        self.go_state_init()

    def stringToMacAddr(self, uri):
        regex = re.compile('[^a-zA-Z]')
        uri = regex.sub('', uri)

        l = len(uri)
        if l > 6:
            uri = uri[0:6]
        else:
            uri = uri + uri[0:6 - l]

        return ":".join([hex(ord(x))[-2:] for x in uri])

    def do_state_init(self, event):
        # Initialize gRPC
        self.log.debug("grpc-host-port", self.host_and_port)
        self.channel = grpc.insecure_channel(self.host_and_port)
        self.channel_ready_future = grpc.channel_ready_future(self.channel)

        self.log.info('openolt-device-created', device_id=self.device_id)

    def post_init(self, event):
        self.log.debug('post_init')

        # We have reached init state, starting the indications thread

        # Catch RuntimeError exception
        try:
            # Start indications thread
            self.indications_thread_handle = threading.Thread(
                target=self.indications_thread)
            # Old getter/setter API for daemon; use it directly as a
            # property instead. The Jinkins error will happon on the reason of
            # Exception in thread Thread-1 (most likely raised # during
            # interpreter shutdown)
            self.log.debug('starting indications thread')
            self.indications_thread_handle.setDaemon(True)
            self.indications_thread_handle.start()
        except Exception as e:
            self.log.exception('post_init failed', e=e)

    @inlineCallbacks
    def do_state_connected(self, event):
        self.log.debug("do_state_connected")

        self.stub = openolt_pb2_grpc.OpenoltStub(self.channel)

        delay = 1
        while True:
            try:
                self.device_info = self.stub.GetDeviceInfo(openolt_pb2.Empty())
                break
            except Exception as e:
                reraise = True
                if delay > 120:
                    self.log.error("gRPC failure too many times")
                else:
                    self.log.warn("gRPC failure, retry in %ds: %s" %
                                  (delay, repr(e)))
                    time.sleep(delay)
                    delay += delay
                    reraise = False

                if reraise:
                    raise

        self.log.info('Device connected', device_info=self.device_info)

        # TODO NEW CORE: logical device id is no longer available. use real device id for now
        self.logical_device_id = self.device_id
        dpid = self.device_info.device_id
        serial_number = self.device_info.device_serial_number

        if dpid is None: dpid = self.dpid
        if serial_number is None: serial_number = self.serial_number

        if dpid == None or dpid == '':
            uri = self.host_and_port.split(":")[0]
            try:
                socket.inet_pton(socket.AF_INET, uri)
                dpid = '00:00:' + self.ip_hex(uri)
            except socket.error:
                # this is not an IP
                dpid = self.stringToMacAddr(uri)

        if serial_number == None or serial_number == '':
            serial_number = self.host_and_port

        self.log.info('creating-openolt-device',
                      dp_id=dpid,
                      serial_number=serial_number)

        self.device.root = True
        self.device.serial_number = serial_number
        self.device.vendor = self.device_info.vendor
        self.device.model = self.device_info.model
        self.device.hardware_version = self.device_info.hardware_version
        self.device.firmware_version = self.device_info.firmware_version

        # TODO: check for uptime and reboot if too long (VOL-1192)

        self.device.connect_status = ConnectStatus.REACHABLE
        self.device.mac_address = dpid
        yield self.core_proxy.device_update(self.device)

        self.resource_mgr = self.resource_mgr_class(self.device_id,
                                                    self.host_and_port,
                                                    self.extra_args,
                                                    self.device_info)
        self.platform = self.platform_class(self.log, self.resource_mgr)
        self.flow_mgr = self.flow_mgr_class(self.core_proxy,
                                            self.adapter_proxy, self.log,
                                            self.stub, self.device_id,
                                            self.logical_device_id,
                                            self.platform, self.resource_mgr)

        self.alarm_mgr = self.alarm_mgr_class(self.log, self.core_proxy,
                                              self.device_id,
                                              self.logical_device_id,
                                              self.platform,
                                              self.serial_number)
        self.stats_mgr = self.stats_mgr_class(self, self.log, self.platform)
        self.bw_mgr = self.bw_mgr_class(self.log, self.core_proxy)

        self.connected = True

    @inlineCallbacks
    def do_state_up(self, event):
        self.log.debug("do_state_up")

        yield self.core_proxy.device_state_update(
            self.device_id,
            connect_status=ConnectStatus.REACHABLE,
            oper_status=OperStatus.ACTIVE)
        self.log.debug("done_state_up")

    @inlineCallbacks
    def do_state_down(self, event):
        self.log.debug("do_state_down")
        yield self.core_proxy.device_state_update(
            self.device_id,
            connect_status=ConnectStatus.UNREACHABLE,
            oper_status=OperStatus.UNKNOWN)
        self.log.debug("done_state_down")

    # def post_up(self, event):
    #     self.log.debug('post-up')
    #     self.flow_mgr.reseed_flows()

    def post_down(self, event):
        self.log.debug('post_down')
        self.flow_mgr.reset_flows()

    def indications_thread(self):
        self.log.debug('starting-indications-thread')
        self.log.debug('connecting to olt', device_id=self.device_id)
        self.channel_ready_future.result()  # blocking call
        self.log.info('connected to olt', device_id=self.device_id)
        self.go_state_connected()

        # TODO: thread timing issue.  stub isnt ready yet from above go_state_connected (which doesnt block)
        # Don't continue until connected is done
        while (not self.connected):
            time.sleep(0.5)

        self.indications = self.stub.EnableIndication(openolt_pb2.Empty())

        while True:
            try:
                # get the next indication from olt
                ind = next(self.indications)
            except Exception as e:
                self.log.warn('gRPC connection lost', error=e)
                reactor.callFromThread(self.go_state_down)
                reactor.callFromThread(self.go_state_init)
                break
            else:
                self.log.debug("rx indication", indication=ind)

                # indication handlers run in the main event loop
                if ind.HasField('olt_ind'):
                    reactor.callFromThread(self.olt_indication, ind.olt_ind)
                elif ind.HasField('intf_ind'):
                    reactor.callFromThread(self.intf_indication, ind.intf_ind)
                elif ind.HasField('intf_oper_ind'):
                    reactor.callFromThread(self.intf_oper_indication,
                                           ind.intf_oper_ind)
                elif ind.HasField('onu_disc_ind'):
                    reactor.callFromThread(self.onu_discovery_indication,
                                           ind.onu_disc_ind)
                elif ind.HasField('onu_ind'):
                    reactor.callFromThread(self.onu_indication, ind.onu_ind)
                elif ind.HasField('omci_ind'):
                    reactor.callFromThread(self.omci_indication, ind.omci_ind)
                elif ind.HasField('pkt_ind'):
                    reactor.callFromThread(self.packet_indication, ind.pkt_ind)
                elif ind.HasField('port_stats'):
                    reactor.callFromThread(
                        self.stats_mgr.port_statistics_indication,
                        ind.port_stats)
                elif ind.HasField('flow_stats'):
                    reactor.callFromThread(
                        self.stats_mgr.flow_statistics_indication,
                        ind.flow_stats)
                elif ind.HasField('alarm_ind'):
                    reactor.callFromThread(self.alarm_mgr.process_alarms,
                                           ind.alarm_ind)
                else:
                    self.log.warn('unknown indication type')

    def olt_indication(self, olt_indication):
        if olt_indication.oper_state == "up":
            self.go_state_up()
        elif olt_indication.oper_state == "down":
            self.go_state_down()

    def intf_indication(self, intf_indication):
        self.log.debug("intf indication",
                       intf_id=intf_indication.intf_id,
                       oper_state=intf_indication.oper_state)

        if intf_indication.oper_state == "up":
            oper_status = OperStatus.ACTIVE
        else:
            oper_status = OperStatus.DISCOVERED

        # add_port update the port if it exists
        self.add_port(intf_indication.intf_id, Port.PON_OLT, oper_status)

    def intf_oper_indication(self, intf_oper_indication):
        self.log.debug("Received interface oper state change indication",
                       intf_id=intf_oper_indication.intf_id,
                       type=intf_oper_indication.type,
                       oper_state=intf_oper_indication.oper_state)

        if intf_oper_indication.oper_state == "up":
            oper_state = OperStatus.ACTIVE
        else:
            oper_state = OperStatus.DISCOVERED

        if intf_oper_indication.type == "nni":

            # add_(logical_)port update the port if it exists
            self.add_port(intf_oper_indication.intf_id, Port.ETHERNET_NNI,
                          oper_state)

        elif intf_oper_indication.type == "pon":
            # FIXME - handle PON oper state change
            pass

    @inlineCallbacks
    def onu_discovery_indication(self, onu_disc_indication):
        intf_id = onu_disc_indication.intf_id
        serial_number = onu_disc_indication.serial_number

        serial_number_str = self.stringify_serial_number(serial_number)

        self.log.debug("onu discovery indication",
                       intf_id=intf_id,
                       serial_number=serial_number_str)

        if serial_number_str in self.seen_discovery_indications:
            self.log.debug("skipping-seen-onu-discovery-indication",
                           intf_id=intf_id,
                           serial_number=serial_number_str)
            return
        else:
            self.seen_discovery_indications.append(serial_number_str)

        self.indication_retries = 0
        # Post ONU Discover alarm  20180809_0805
        try:
            OnuDiscoveryAlarm(self.alarm_mgr.alarms,
                              pon_id=intf_id,
                              serial_number=serial_number_str).raise_alarm()
        except Exception as disc_alarm_error:
            self.log.exception("onu-discovery-alarm-error",
                               errmsg=disc_alarm_error.message)
            # continue for now.

        onu_device = yield self.core_proxy.get_child_device(
            self.device_id, serial_number=serial_number_str)

        if onu_device is None:
            try:
                onu_id = self.resource_mgr.get_onu_id(intf_id)
                if onu_id is None:
                    raise Exception("onu-id-unavailable")

                self.add_onu_device(
                    intf_id,
                    self.platform.intf_id_to_port_no(intf_id, Port.PON_OLT),
                    onu_id, serial_number)
                self.activate_onu(intf_id, onu_id, serial_number,
                                  serial_number_str)
            except Exception as e:
                self.log.exception('onu-activation-failed', e=e)

        else:
            if onu_device.connect_status != ConnectStatus.REACHABLE:
                yield self.core_proxy.device_state_update(
                    onu_device.id, connect_status=ConnectStatus.REACHABLE)

            onu_id = onu_device.proxy_address.onu_id
            if onu_device.oper_status == OperStatus.DISCOVERED \
                    or onu_device.oper_status == OperStatus.ACTIVATING:
                self.log.debug("ignore onu discovery indication, \
                               the onu has been discovered and should be \
                               activating shorlty",
                               intf_id=intf_id,
                               onu_id=onu_id,
                               state=onu_device.oper_status)
            elif onu_device.oper_status == OperStatus.ACTIVE:
                self.log.warn("onu discovery indication whereas onu is \
                              supposed to be active",
                              intf_id=intf_id,
                              onu_id=onu_id,
                              state=onu_device.oper_status)
            elif onu_device.oper_status == OperStatus.UNKNOWN:
                self.log.info("onu in unknown state, recovering from olt \
                              reboot probably, activate onu",
                              intf_id=intf_id,
                              onu_id=onu_id,
                              serial_number=serial_number_str)

                yield self.core_proxy.device_state_update(
                    onu_device.id, oper_status=OperStatus.DISCOVERED)

                try:
                    self.activate_onu(intf_id, onu_id, serial_number,
                                      serial_number_str)
                except Exception as e:
                    self.log.error('onu-activation-error',
                                   serial_number=serial_number_str,
                                   error=e)
            else:
                self.log.warn('unexpected state',
                              onu_id=onu_id,
                              onu_device_oper_state=onu_device.oper_status)

    @inlineCallbacks
    def onu_indication(self, onu_indication):
        self.log.debug("onu indication",
                       intf_id=onu_indication.intf_id,
                       onu_id=onu_indication.onu_id,
                       serial_number=onu_indication.serial_number,
                       oper_state=onu_indication.oper_state,
                       admin_state=onu_indication.admin_state)
        try:
            serial_number_str = self.stringify_serial_number(
                onu_indication.serial_number)
        except Exception as e:
            serial_number_str = None

        onu_device = None
        found_in_cache = False
        onu_key = self.form_onu_key(onu_indication.intf_id,
                                    onu_indication.onu_id)

        if onu_key in self.onu_cache:
            onu_cache_device = self.onu_cache[onu_key]
            found_in_cache = True
            self.log.debug('lookup-updated-device', serial_number=serial_number_str)
            # If ONU id is discovered before then use GetDevice to get onuDevice because it is cheaper.
            onu_device = yield self.core_proxy.get_device(onu_cache_device.id)
        else:
            if serial_number_str is not None:
                self.log.debug('lookup-device-by-serial-number', serial_number=serial_number_str)
                onu_device = yield self.core_proxy.get_child_device(
                    self.device_id, serial_number=serial_number_str)
            else:
                self.log.debug('lookup-device-by-parent-port', intf_id=onu_indication.intf_id, onu_id=onu_indication.onu_id)
                onu_device = yield self.core_proxy.get_child_device(
                    self.device_id,
                    parent_port_no=self.platform.intf_id_to_port_no(
                        onu_indication.intf_id, Port.PON_OLT),
                    onu_id=onu_indication.onu_id)

        if onu_device is None:
            self.log.warn('onu not found in cache nor core, trying again',
                           intf_id=onu_indication.intf_id,
                           onu_id=onu_indication.onu_id)
            if self.indication_retries < 10:
                self.indication_retries += 1
                reactor.callLater(3, self.onu_indication, onu_indication)
            else:
                self.log.error('onu not found in cache nor core, giving up',
                               intf_id=onu_indication.intf_id,
                               onu_id=onu_indication.onu_id)
            return

        self.log.debug('onu-device-found', onu_device=onu_device)

        self.onus[onu_key] = OnuDevice(onu_device.id, onu_device.type,
                                       serial_number_str,
                                       onu_indication.onu_id,
                                       onu_indication.intf_id)

        if self.platform.intf_id_from_pon_port_no(onu_device.parent_port_no) \
                != onu_indication.intf_id:
            self.log.warn(
                'ONU-is-on-a-different-intf-id-now',
                previous_intf_id=self.platform.intf_id_from_pon_port_no(
                    onu_device.parent_port_no),
                current_intf_id=onu_indication.intf_id)
            # FIXME - handle intf_id mismatch (ONU move?)

        if onu_device.proxy_address.onu_id != onu_indication.onu_id:
            # FIXME - handle onu id mismatch
            self.log.warn(
                'ONU-id-mismatch, can happen if both voltha and '
                'the olt rebooted',
                expected_onu_id=onu_device.proxy_address.onu_id,
                received_onu_id=onu_indication.onu_id)

        # Admin state
        if onu_indication.admin_state == 'down':
            if onu_indication.oper_state != 'down':
                self.log.error('ONU-admin-state-down-and-oper-status-not-down',
                               oper_state=onu_indication.oper_state)
                # Forcing the oper state change code to execute
                onu_indication.oper_state = 'down'

            # Port and logical port update is taken care of by oper state block

        elif onu_indication.admin_state == 'up':
            pass

        else:
            self.log.warn('Invalid-or-not-implemented-admin-state',
                          received_admin_state=onu_indication.admin_state)

        self.log.debug('admin-state-dealt-with')

        # Operating state
        if onu_indication.oper_state == 'down':

            if onu_device.connect_status != ConnectStatus.UNREACHABLE:
                yield self.core_proxy.device_state_update(
                    onu_device.id, connect_status=ConnectStatus.UNREACHABLE)

            # Move to discovered state
            self.log.debug('onu-oper-state-is-down')

            if onu_device.oper_status != OperStatus.DISCOVERED:
                yield self.core_proxy.device_state_update(
                    onu_device.id, oper_status=OperStatus.DISCOVERED)

            self.log.debug('inter-adapter-send-onu-ind',
                           onu_indication=onu_indication)

            # TODO NEW CORE do not hardcode adapter name. Handler needs Adapter reference
            yield self.adapter_proxy.send_inter_adapter_message(
                msg=onu_indication,
                type=InterAdapterMessageType.ONU_IND_REQUEST,
                from_adapter="openolt",
                to_adapter=onu_device.type,
                to_device_id=onu_device.id)

        elif onu_indication.oper_state == 'up':

            if onu_device.connect_status != ConnectStatus.REACHABLE:
                yield self.core_proxy.device_state_update(
                    onu_device.id, connect_status=ConnectStatus.REACHABLE)

            if not found_in_cache and onu_device.oper_status != OperStatus.DISCOVERED:
                if serial_number_str not in self.seen_discovery_indications:
                    self.log.debug("Ignore ONU indication",
                                   intf_id=onu_indication.intf_id,
                                   onu_id=onu_indication.onu_id,
                                   state=onu_device.oper_status,
                                   msg_oper_state=onu_indication.oper_state)
                    return

            self.log.debug('inter-adapter-send-onu-ind',
                           onu_indication=onu_indication)

            # TODO NEW CORE do not hardcode adapter name. Handler needs Adapter reference
            yield self.adapter_proxy.send_inter_adapter_message(
                msg=onu_indication,
                type=InterAdapterMessageType.ONU_IND_REQUEST,
                from_adapter="openolt",
                to_adapter=onu_device.type,
                to_device_id=onu_device.id)

        else:
            self.log.warn('Not-implemented-or-invalid-value-of-oper-state',
                          oper_state=onu_indication.oper_state)

    @inlineCallbacks
    def onu_ports_down(self, onu_device, oper_state):
        pass
        # Set port oper state to Discovered
        # add port will update port if it exists
        # yield self.core_proxy.add_port(
        #    self.device_id,
        #    Port(
        #        port_no=uni_no,
        #        label=uni_name,
        #        type=Port.ETHERNET_UNI,
        #        admin_state=onu_device.admin_state,
        #        oper_status=oper_state))
        # TODO this should be downning ports in onu adatper

    @inlineCallbacks
    def omci_indication(self, omci_indication):

        self.log.debug("omci indication",
                       intf_id=omci_indication.intf_id,
                       onu_id=omci_indication.onu_id)
        onu_in_cache = self.onus.get(
            self.form_onu_key(omci_indication.intf_id, omci_indication.onu_id),
            None)
        if onu_in_cache is None:
            self.log.debug('omci indication for a device not in cache.',
                           intf_id=omci_indication.intf_id,
                           onu_id=omci_indication.onu_id)
            onu_device = yield self.core_proxy.get_child_device(
                self.device_id,
                onu_id=omci_indication.onu_id,
                parent_port_no=self.platform.intf_id_to_port_no(
                    omci_indication.intf_id, Port.PON_OLT),
            )
            onu_device_type = onu_device.type
            onu_device_id = onu_device.id
            try:
                serial_number_str = self.stringify_serial_number(
                    omci_indication.serial_number)
            except Exception as e:
                serial_number_str = None

            #if not exist in cache, then add to cache.
            onu_key = self.form_onu_key(omci_indication.intf_id,
                                        omci_indication.onu_id)
            self.onus[onu_key] = OnuDevice(onu_device.id, onu_device.type,
                                           serial_number_str,
                                           omci_indication.onu_id,
                                           omci_indication.intf_id)
        else:
            onu_device_type = onu_in_cache.device_type
            onu_device_id = onu_in_cache.device_id

        omci_msg = InterAdapterOmciMessage(message=omci_indication.pkt)

        self.log.debug('inter-adapter-send-omci', omci_msg=omci_msg)

        # TODO NEW CORE do not hardcode adapter name. Handler needs Adapter reference
        yield self.adapter_proxy.send_inter_adapter_message(
            msg=omci_msg,
            type=InterAdapterMessageType.OMCI_REQUEST,
            from_adapter="openolt",
            to_adapter=onu_device_type,
            to_device_id=onu_device_id)

    @inlineCallbacks
    def packet_indication(self, pkt_indication):

        self.log.debug("packet indication",
                       intf_type=pkt_indication.intf_type,
                       intf_id=pkt_indication.intf_id,
                       port_no=pkt_indication.port_no,
                       cookie=pkt_indication.cookie,
                       gemport_id=pkt_indication.gemport_id,
                       flow_id=pkt_indication.flow_id)

        if pkt_indication.intf_type == "pon":
            if pkt_indication.port_no:
                port_num = pkt_indication.port_no
            else:  # TODO Remove this else block after openolt device has been fully rolled out with cookie protobuf change
                try:
                    onu_id_uni_id = self.resource_mgr.get_onu_uni_from_ponport_gemport(
                        pkt_indication.intf_id, pkt_indication.gemport_id)
                    onu_id = int(onu_id_uni_id[0])
                    uni_id = int(onu_id_uni_id[1])
                    self.log.debug("packet indication-kv",
                                   onu_id=onu_id,
                                   uni_id=uni_id)
                    if onu_id is None:
                        raise Exception("onu-id-none")
                    if uni_id is None:
                        raise Exception("uni-id-none")
                    port_num = self.platform.mk_uni_port_num(
                        pkt_indication.intf_id, onu_id, uni_id)
                except Exception as e:
                    self.log.error("no-onu-reference-for-gem",
                                   gemport_id=pkt_indication.gemport_id,
                                   e=e)
                    return

        elif pkt_indication.intf_type == "nni":
            port_num = self.platform.intf_id_to_port_no(
                pkt_indication.intf_id, Port.ETHERNET_NNI)

        pkt = Ether(pkt_indication.pkt)

        self.log.debug("packet indication",
                       device_id=self.device_id,
                       port_num=port_num)

        yield self.core_proxy.send_packet_in(device_id=self.device_id,
                                             port=port_num,
                                             packet=str(pkt))

    def packet_out(self, egress_port, msg):
        pkt = Ether(msg)
        self.log.debug('packet out',
                       egress_port=egress_port,
                       device_id=self.device_id,
                       packet=str(pkt).encode("HEX"))

        # Find port type
        egress_port_type = self.platform.intf_id_to_port_type_name(egress_port)
        if egress_port_type == Port.ETHERNET_UNI:

            if pkt.haslayer(Dot1Q):
                outer_shim = pkt.getlayer(Dot1Q)
                if isinstance(outer_shim.payload, Dot1Q):
                    # If double tag, remove the outer tag
                    payload = (
                        Ether(src=pkt.src, dst=pkt.dst, type=outer_shim.type) /
                        outer_shim.payload)
                else:
                    payload = pkt
            else:
                payload = pkt

            send_pkt = binascii.unhexlify(str(payload).encode("HEX"))

            self.log.debug(
                'sending-packet-to-ONU',
                egress_port=egress_port,
                intf_id=self.platform.intf_id_from_uni_port_num(egress_port),
                onu_id=self.platform.onu_id_from_port_num(egress_port),
                uni_id=self.platform.uni_id_from_port_num(egress_port),
                port_no=egress_port,
                packet=str(payload).encode("HEX"))

            onu_pkt = openolt_pb2.OnuPacket(
                intf_id=self.platform.intf_id_from_uni_port_num(egress_port),
                onu_id=self.platform.onu_id_from_port_num(egress_port),
                port_no=egress_port,
                pkt=send_pkt)

            self.stub.OnuPacketOut(onu_pkt)

        elif egress_port_type == Port.ETHERNET_NNI:
            self.log.debug('sending-packet-to-uplink',
                           egress_port=egress_port,
                           packet=str(pkt).encode("HEX"))

            send_pkt = binascii.unhexlify(str(pkt).encode("HEX"))

            uplink_pkt = openolt_pb2.UplinkPacket(
                intf_id=self.platform.intf_id_from_nni_port_num(egress_port),
                pkt=send_pkt)

            self.stub.UplinkPacketOut(uplink_pkt)

        else:
            self.log.warn('Packet-out-to-this-interface-type-not-implemented',
                          egress_port=egress_port,
                          port_type=egress_port_type)

    def process_inter_adapter_message(self, request):
        self.log.debug('process-inter-adapter-message', msg=request)
        try:
            if request.header.type == InterAdapterMessageType.OMCI_REQUEST:
                omci_msg = InterAdapterOmciMessage()
                request.body.Unpack(omci_msg)
                self.log.debug('inter-adapter-recv-omci', omci_msg=omci_msg)

                #onu_device_id = request.header.to_device_id
                #onu_device = yield self.core_proxy.get_device(onu_device_id)
                self.send_proxied_message(omci_msg)

            else:
                self.log.error("inter-adapter-unhandled-type", request=request)

        except Exception as e:
            self.log.exception("error-processing-inter-adapter-message", e=e)

    def send_proxied_message(self, omci_msg):

        if omci_msg.connect_status != ConnectStatus.REACHABLE:
            self.log.debug('ONU is not reachable, cannot send OMCI',
                           intf_id=omci_msg.proxy_address.channel_id,
                           onu_id=omci_msg.proxy_address.onu_id)
            return

        omci = openolt_pb2.OmciMsg(intf_id=omci_msg.proxy_address.channel_id,
                                   onu_id=omci_msg.proxy_address.onu_id,
                                   pkt=str(omci_msg.message))
        self.stub.OmciMsgOut(omci)

        self.log.debug("omci-message-sent",
                       intf_id=omci_msg.proxy_address.channel_id,
                       onu_id=omci_msg.proxy_address.onu_id,
                       pkt=str(omci_msg.message))

    @inlineCallbacks
    def add_onu_device(self, intf_id, port_no, onu_id, serial_number):
        self.log.info("adding-onu",
                      port_no=port_no,
                      onu_id=onu_id,
                      serial_number=serial_number)

        serial_number_str = self.stringify_serial_number(serial_number)

        onu_device = yield self.core_proxy.child_device_detected(
            parent_device_id=self.device_id,
            parent_port_no=port_no,
            child_device_type='',
            channel_id=intf_id,
            vendor_id=serial_number.vendor_id,
            serial_number=serial_number_str,
            onu_id=onu_id)

        self.log.debug("onu-added",
                       onu_id=onu_id,
                       port_no=port_no,
                       serial_number=serial_number_str)

        self.log.debug('Adding ONU device to the cache',
                       intf_id=intf_id,
                       onu_id=onu_id)
        onu_key = self.form_onu_key(intf_id, onu_id)
        self.onu_cache[onu_key] = onu_device

        yield self.core_proxy.device_state_update(
            onu_device.id,
            oper_status=OperStatus.DISCOVERED,
            connect_status=ConnectStatus.REACHABLE)

        self.log.debug("set-onu-discovered",
                       onu_id=onu_id,
                       port_no=port_no,
                       serial_number=serial_number_str,
                       onu_device=onu_device)
        return

    def get_ofp_device_info(self, device):
        self.log.info('get_ofp_device_info', device_id=device.id)

        mfr_desc = self.device_info.vendor
        sw_desc = self.device_info.firmware_version
        hw_desc = self.device_info.model
        if self.device_info.hardware_version:
            hw_desc += '-' + self.device_info.hardware_version

        return SwitchCapability(
            desc=ofp_desc(hw_desc=hw_desc,
                          sw_desc=sw_desc,
                          serial_num=device.serial_number),
            switch_features=ofp_switch_features(
                n_buffers=
                256,  # Max packets buffered at once          # TODO fake for now
                n_tables=
                2,  # Number of tables supported by datapath   # TODO fake for now
                capabilities=
                (  #Bitmap of support "ofp_capabilities"    # TODO fake for now
                    OFPC_FLOW_STATS
                    | OFPC_TABLE_STATS
                    | OFPC_PORT_STATS
                    | OFPC_GROUP_STATS)))

    def get_ofp_port_info(self, device, port_no):
        self.log.info('get_ofp_port_info',
                      port_no=port_no,
                      device_id=device.id)
        cap = OFPPF_1GB_FD | OFPPF_FIBER
        return PortCapability(port=LogicalPort(ofp_port=ofp_port(
            hw_addr=mac_str_to_tuple(self._get_mac_form_port_no(port_no)),
            config=0,
            state=OFPPS_LIVE,
            curr=cap,
            advertised=cap,
            peer=cap,
            curr_speed=OFPPF_1GB_FD,
            max_speed=OFPPF_1GB_FD),
                                               device_id=device.id,
                                               device_port_no=port_no))

    def port_name(self, port_no, port_type, intf_id=None, serial_number=None):
        if port_type is Port.ETHERNET_NNI:
            return "nni-" + str(port_no)
        elif port_type is Port.PON_OLT:
            return "pon" + str(intf_id)
        elif port_type is Port.ETHERNET_UNI:
            assert False, 'local UNI management not supported'

    def _get_mac_form_port_no(self, port_no):
        mac = ''
        for i in range(4):
            mac = ':%02x' % ((port_no >> (i * 8)) & 0xff) + mac
        return '00:00' + mac

    @inlineCallbacks
    def add_port(self, intf_id, port_type, oper_status):
        port_no = self.platform.intf_id_to_port_no(intf_id, port_type)

        label = self.port_name(port_no, port_type, intf_id)

        self.log.debug('adding-port',
                       port_no=port_no,
                       label=label,
                       port_type=port_type)

        port = Port(port_no=port_no,
                    label=label,
                    type=port_type,
                    admin_state=AdminState.ENABLED,
                    oper_status=oper_status)

        yield self.core_proxy.port_created(self.device_id, port)

    @inlineCallbacks
    def delete_port(self, child_serial_number):
        ports = self.proxy.get('/devices/{}/ports'.format(self.device_id))
        for port in ports:
            if port.label == child_serial_number:
                self.log.debug('delete-port',
                               onu_serial_number=child_serial_number,
                               port=port)
                yield self.core_proxy.port_removed(self.device_id, port)
                return

    def update_flow_table(self, flow_changes):

        self.log.debug("update_flow_table", flow_changes=flow_changes)

        flows_to_add = flow_changes.to_add.items
        flows_to_remove = flow_changes.to_remove.items

        if not self.is_state_up():
            self.log.info('The OLT is not up, we cannot update flows',
                          flows_to_add=[f.id for f in flows_to_add],
                          flows_to_remove=[f.id for f in flows_to_remove])
            return

        self.log.debug('flows update',
                       flows_to_add=flows_to_add,
                       flows_to_remove=flows_to_remove)

        for flow in flows_to_add:

            try:
                self.flow_mgr.add_flow(flow)
            except Exception as e:
                self.log.error('failed to add flow', flow=flow, e=e)

        for flow in flows_to_remove:

            try:
                self.flow_mgr.remove_flow(flow)
            except Exception as e:
                self.log.error('failed to remove flow', flow=flow, e=e)

        # TODO NEW CORE: Core keeps track of logical flows. no need to keep track.  verify, especially olt reboot!
        #self.flow_mgr.repush_all_different_flows()

    # There has to be a better way to do this
    def ip_hex(self, ip):
        octets = ip.split(".")
        hex_ip = []
        for octet in octets:
            octet_hex = hex(int(octet))
            octet_hex = octet_hex.split('0x')[1]
            octet_hex = octet_hex.rjust(2, '0')
            hex_ip.append(octet_hex)
        return ":".join(hex_ip)

    def stringify_vendor_specific(self, vendor_specific):
        return ''.join(
            str(i) for i in [
                hex(ord(vendor_specific[0]) >> 4 & 0x0f)[2:],
                hex(ord(vendor_specific[0]) & 0x0f)[2:],
                hex(ord(vendor_specific[1]) >> 4 & 0x0f)[2:],
                hex(ord(vendor_specific[1]) & 0x0f)[2:],
                hex(ord(vendor_specific[2]) >> 4 & 0x0f)[2:],
                hex(ord(vendor_specific[2]) & 0x0f)[2:],
                hex(ord(vendor_specific[3]) >> 4 & 0x0f)[2:],
                hex(ord(vendor_specific[3]) & 0x0f)[2:]
            ])

    def stringify_serial_number(self, serial_number):
        return ''.join([
            serial_number.vendor_id,
            self.stringify_vendor_specific(serial_number.vendor_specific)
        ])

    def destringify_serial_number(self, serial_number_str):
        serial_number = openolt_pb2.SerialNumber(
            vendor_id=serial_number_str[:4].encode('utf-8'),
            vendor_specific=binascii.unhexlify(serial_number_str[4:]))
        return serial_number

    def disable(self):
        self.log.debug('sending-deactivate-olt-message',
                       device_id=self.device_id)

        try:
            # Send grpc call
            self.stub.DisableOlt(openolt_pb2.Empty())
            # The resulting indication will bring the OLT down
            # self.go_state_down()
            self.log.info('openolt device disabled')
        except Exception as e:
            self.log.error('Failure to disable openolt device', error=e)

    def delete(self):
        self.log.info('deleting-olt', device_id=self.device_id)

        # Clears up the data from the resource manager KV store
        # for the device
        del self.resource_mgr

        try:
            # Rebooting to reset the state
            self.reboot()
            # Removing logical device
        except Exception as e:
            self.log.error('Failure to delete openolt device', error=e)
            raise e
        else:
            self.log.info('successfully-deleted-olt', device_id=self.device_id)

    def reenable(self):
        self.log.debug('reenabling-olt', device_id=self.device_id)

        try:
            self.stub.ReenableOlt(openolt_pb2.Empty())

        except Exception as e:
            self.log.error('Failure to reenable openolt device', error=e)
        else:
            self.log.info('openolt device reenabled')

    def activate_onu(self, intf_id, onu_id, serial_number, serial_number_str):
        pir = self.bw_mgr.pir(serial_number_str)
        self.log.debug("activating-onu",
                       intf_id=intf_id,
                       onu_id=onu_id,
                       serial_number_str=serial_number_str,
                       serial_number=serial_number,
                       pir=pir)
        onu = openolt_pb2.Onu(intf_id=intf_id,
                              onu_id=onu_id,
                              serial_number=serial_number,
                              pir=pir)
        self.stub.ActivateOnu(onu)
        self.log.info('onu-activated', serial_number=serial_number_str)

    @inlineCallbacks
    def delete_child_device(self, child_device):
        self.log.debug('sending-deactivate-onu',
                       olt_device_id=self.device_id,
                       onu_device=child_device,
                       onu_serial_number=child_device.serial_number)
        try:
            yield self.core_proxy.child_device_removed(self.device_id,
                                                       child_device.id,
                                                       child_device)
        except Exception as e:
            self.log.error('core_proxy error', error=e)
        try:
            self.delete_logical_port(child_device)
        except Exception as e:
            self.log.error('logical_port delete error', error=e)
        try:
            self.delete_port(child_device.serial_number)
        except Exception as e:
            self.log.error('port delete error', error=e)
        serial_number = self.destringify_serial_number(
            child_device.serial_number)
        # TODO FIXME - For each uni.
        # TODO FIXME - Flows are not deleted
        uni_id = 0  # FIXME
        self.flow_mgr.delete_tech_profile_instance(
            child_device.proxy_address.channel_id,
            child_device.proxy_address.onu_id, uni_id)
        pon_intf_id_onu_id = (child_device.proxy_address.channel_id,
                              child_device.proxy_address.onu_id, uni_id)
        # Free any PON resources that were reserved for the ONU
        self.resource_mgr.free_pon_resources_for_onu(pon_intf_id_onu_id)

        onu = openolt_pb2.Onu(intf_id=child_device.proxy_address.channel_id,
                              onu_id=child_device.proxy_address.onu_id,
                              serial_number=serial_number)
        self.stub.DeleteOnu(onu)

    def reboot(self):
        self.log.debug('rebooting openolt device', device_id=self.device_id)
        try:
            self.stub.Reboot(openolt_pb2.Empty())
        except Exception as e:
            self.log.error('something went wrong with the reboot', error=e)
        else:
            self.log.info('device rebooted')

    def trigger_statistics_collection(self):
        try:
            self.stub.CollectStatistics(openolt_pb2.Empty())
        except Exception as e:
            self.log.error('Error while triggering statistics collection',
                           error=e)
        else:
            self.log.info('statistics requested')

    def simulate_alarm(self, alarm):
        self.alarm_mgr.simulate_alarm(alarm)

    def form_onu_key(self, intf_id, onu_id):
        return str(intf_id) + "." + str(onu_id)


class OnuDevice(object):
    def __init__(self, device_id, device_type, serialnumber, onu_id, intf_id):
        self.device_id = device_id
        self.device_type = device_type
        self.serialnumber = serialnumber
        self.onu_id = onu_id
        self.intf_id = intf_id
