#
# 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 copy
from twisted.internet import reactor
import grpc

from voltha.protos.openflow_13_pb2 import OFPXMC_OPENFLOW_BASIC, \
    ofp_flow_stats, ofp_match, OFPMT_OXM, Flows, FlowGroups, OFPXMT_OFB_IN_PORT
import voltha.core.flow_decomposer as fd
import openolt_platform as platform
from voltha.adapters.openolt.protos import openolt_pb2
from voltha.registry import registry

HSIA_FLOW_INDEX = 0  # FIXME
DHCP_FLOW_INDEX = 1  # FIXME
DHCP_DOWNLINK_FLOW_INDEX = 6  # FIXME
EAPOL_FLOW_INDEX = 2  # FIXME
EAPOL_DOWNLINK_FLOW_INDEX = 3  # FIXME
EAPOL_DOWNLINK_SECONDARY_FLOW_INDEX = 4  # FIXME
EAPOL_UPLINK_SECONDARY_FLOW_INDEX = 5  # FIXME


EAP_ETH_TYPE = 0x888e

# FIXME - see also BRDCM_DEFAULT_VLAN in broadcom_onu.py
DEFAULT_MGMT_VLAN = 4091


class OpenOltFlowMgr(object):

    def __init__(self, log, stub, device_id, logical_device_id):
        self.log = log
        self.stub = stub
        self.device_id = device_id
        self.logical_device_id = logical_device_id
        self.logical_flows_proxy = registry('core').get_proxy(
            '/logical_devices/{}/flows'.format(self.logical_device_id))
        self.flows_proxy = registry('core').get_proxy(
            '/devices/{}/flows'.format(self.device_id))
        self.root_proxy = registry('core').get_proxy('/')
        self.fd_object = fd.FlowDecomposer()

    def add_flow(self, flow):
        self.log.debug('add flow', flow=flow)
        classifier_info = dict()
        action_info = dict()


        for field in fd.get_ofb_fields(flow):
            if field.type == fd.ETH_TYPE:
                classifier_info['eth_type'] = field.eth_type
                self.log.debug('field-type-eth-type',
                               eth_type=classifier_info['eth_type'])
            elif field.type == fd.IP_PROTO:
                classifier_info['ip_proto'] = field.ip_proto
                self.log.debug('field-type-ip-proto',
                               ip_proto=classifier_info['ip_proto'])
            elif field.type == fd.IN_PORT:
                classifier_info['in_port'] = field.port
                self.log.debug('field-type-in-port',
                               in_port=classifier_info['in_port'])
            elif field.type == fd.VLAN_VID:
                classifier_info['vlan_vid'] = field.vlan_vid & 0xfff
                self.log.debug('field-type-vlan-vid',
                               vlan=classifier_info['vlan_vid'])
            elif field.type == fd.VLAN_PCP:
                classifier_info['vlan_pcp'] = field.vlan_pcp
                self.log.debug('field-type-vlan-pcp',
                               pcp=classifier_info['vlan_pcp'])
            elif field.type == fd.UDP_DST:
                classifier_info['udp_dst'] = field.udp_dst
                self.log.debug('field-type-udp-dst',
                               udp_dst=classifier_info['udp_dst'])
            elif field.type == fd.UDP_SRC:
                classifier_info['udp_src'] = field.udp_src
                self.log.debug('field-type-udp-src',
                               udp_src=classifier_info['udp_src'])
            elif field.type == fd.IPV4_DST:
                classifier_info['ipv4_dst'] = field.ipv4_dst
                self.log.debug('field-type-ipv4-dst',
                               ipv4_dst=classifier_info['ipv4_dst'])
            elif field.type == fd.IPV4_SRC:
                classifier_info['ipv4_src'] = field.ipv4_src
                self.log.debug('field-type-ipv4-src',
                               ipv4_dst=classifier_info['ipv4_src'])
            elif field.type == fd.METADATA:
                classifier_info['metadata'] = field.table_metadata
                self.log.debug('field-type-metadata',
                               metadata=classifier_info['metadata'])
            else:
                raise NotImplementedError('field.type={}'.format(
                    field.type))

        for action in fd.get_actions(flow):
            if action.type == fd.OUTPUT:
                action_info['output'] = action.output.port
                self.log.debug('action-type-output',
                               output=action_info['output'],
                               in_port=classifier_info['in_port'])
            elif action.type == fd.POP_VLAN:
                if fd.get_goto_table_id(flow) is None:
                    self.log.debug('being taken care of by ONU', flow=flow)
                    return
                action_info['pop_vlan'] = True
                self.log.debug('action-type-pop-vlan', in_port=classifier_info['in_port'])
            elif action.type == fd.PUSH_VLAN:
                action_info['push_vlan'] = True
                action_info['tpid'] = action.push.ethertype
                self.log.debug('action-type-push-vlan',
                               push_tpid=action_info['tpid'], in_port=classifier_info['in_port'])
                if action.push.ethertype != 0x8100:
                    self.log.error('unhandled-tpid',
                                   ethertype=action.push.ethertype)
            elif action.type == fd.SET_FIELD:
                # action_info['action_type'] = 'set_field'
                _field = action.set_field.field.ofb_field
                assert (action.set_field.field.oxm_class ==
                        OFPXMC_OPENFLOW_BASIC)
                self.log.debug('action-type-set-field',
                               field=_field, in_port=classifier_info['in_port'])
                if _field.type == fd.VLAN_VID:
                    self.log.debug('set-field-type-vlan-vid',
                                   vlan_vid=_field.vlan_vid & 0xfff)
                    action_info['vlan_vid'] = (_field.vlan_vid & 0xfff)
                else:
                    self.log.error('unsupported-action-set-field-type',
                                   field_type=_field.type)
            else:
                self.log.error('unsupported-action-type',
                               action_type=action.type, in_port=classifier_info['in_port'])

        if fd.get_goto_table_id(flow) is not None and not 'pop_vlan' in \
                action_info:
            self.log.debug('being taken care of by ONU', flow=flow)

        if not 'output' in action_info and 'metadata' in classifier_info:
            #find flow in the next table
            next_flow = self.find_next_flow(flow)
            if next_flow is None:
                return
            action_info['output'] = fd.get_out_port(next_flow)
            for field in fd.get_ofb_fields(next_flow):
                if field.type == fd.VLAN_VID:
                    classifier_info['metadata'] = field.vlan_vid & 0xfff


        (intf_id, onu_id) = platform.extract_access_from_flow(
            classifier_info['in_port'], action_info['output'])


        self.divide_and_add_flow(intf_id, onu_id, classifier_info,
                                 action_info, flow)

    def remove_flow(self, flow):
        self.log.debug('trying to remove flows from logical flow :',
                   logical_flow=flow)
        device_flows_to_remove = []
        device_flows = self.flows_proxy.get('/').items
        for f in device_flows:
            if f.cookie == flow.id:
                device_flows_to_remove.append(f)


        for f in device_flows_to_remove:
            (id, direction) = self.decode_stored_id(f.id)
            flow_to_remove = openolt_pb2.Flow(flow_id=id, flow_type=direction)
            try:
                self.stub.FlowRemove(flow_to_remove)
            except grpc.RpcError as grpc_e:
                if grpc_e.code() == grpc.StatusCode.NOT_FOUND:
                    self.log.debug('This flow does not exist on the switch, '
                                   'normal after an OLT reboot', flow=flow_to_remove)
                else:
                    raise grpc_e

            self.log.debug('flow removed from device', flow=f,
                           flow_key=flow_to_remove)

        if len(device_flows_to_remove) > 0:
            new_flows = []
            flows_ids_to_remove = [f.id for f in device_flows_to_remove]
            for f in device_flows:
                if f.id not in flows_ids_to_remove:
                    new_flows.append(f)

            self.flows_proxy.update('/', Flows(items=new_flows))
            self.log.debug('flows removed from the data store',
                           flow_ids_removed=flows_ids_to_remove,
                           number_of_flows_removed=(len(device_flows) - len(
                               new_flows)), expected_flows_removed=len(
                            device_flows_to_remove))
        else:
            self.log.debug('no device flow to remove for this flow (normal '
                           'for multi table flows)', flow=flow)


    def divide_and_add_flow(self, intf_id, onu_id, classifier,
                            action, flow):

        self.log.debug('sorting flow', intf_id=intf_id, onu_id=onu_id,
                       classifier=classifier, action=action)

        if 'ip_proto' in classifier:
            if classifier['ip_proto'] == 17:
                self.log.debug('dhcp flow add')
                self.add_dhcp_trap(intf_id, onu_id, classifier,
                                   action, flow)
            elif classifier['ip_proto'] == 2:
                self.log.warn('igmp flow add ignored, not implemented yet')
            else:
                self.log.warn("Invalid-Classifier-to-handle",
                               classifier=classifier,
                               action=action)
        elif 'eth_type' in classifier:
            if classifier['eth_type'] == EAP_ETH_TYPE:
                self.log.debug('eapol flow add')
                self.add_eapol_flow(intf_id, onu_id, flow)

        elif 'push_vlan' in action:
            self.add_upstream_data_flow(intf_id, onu_id, classifier, action,
                                      flow)
        elif 'pop_vlan' in action:
            self.add_downstream_data_flow(intf_id, onu_id, classifier,
                                          action, flow)
        else:
            self.log.debug('Invalid-flow-type-to-handle',
                           classifier=classifier,
                           action=action, flow=flow)


    def add_upstream_data_flow(self, intf_id, onu_id, uplink_classifier,
                       uplink_action, logical_flow):


        uplink_classifier['pkt_tag_type'] = 'single_tag'

        self.add_hsia_flow(intf_id, onu_id, uplink_classifier,
                           uplink_action, 'upstream', HSIA_FLOW_INDEX,
                           logical_flow)

        # Secondary EAP on the subscriber vlan
        (eap_active, eap_logical_flow) = self.is_eap_enabled(intf_id, onu_id)
        if eap_active:
            self.add_eapol_flow(intf_id, onu_id, eap_logical_flow,
                uplink_eapol_id=EAPOL_UPLINK_SECONDARY_FLOW_INDEX,
                downlink_eapol_id=EAPOL_DOWNLINK_SECONDARY_FLOW_INDEX,
                vlan_id=uplink_classifier['vlan_vid'])


    def add_downstream_data_flow(self, intf_id, onu_id, downlink_classifier,
                                 downlink_action, flow):
        downlink_classifier['pkt_tag_type'] = 'double_tag'
        # Needed ???? It should be already there
        downlink_action['pop_vlan'] = True
        downlink_action['vlan_vid'] = downlink_classifier['vlan_vid']

        self.add_hsia_flow(intf_id, onu_id, downlink_classifier,
                           downlink_action, 'downstream', HSIA_FLOW_INDEX,
                           flow)

    # To-Do right now only one GEM port is supported, so below method
    # will take care of handling all the p bits.
    # We need to revisit when mulitple gem port per p bits is needed.
    def add_hsia_flow(self, intf_id, onu_id, classifier, action,
                      direction, hsia_id, logical_flow):

        gemport_id = platform.mk_gemport_id(intf_id, onu_id)
        flow_id = platform.mk_flow_id(intf_id, onu_id, hsia_id)

        flow = openolt_pb2.Flow(
                onu_id=onu_id, flow_id=flow_id, flow_type=direction,
                access_intf_id=intf_id, gemport_id=gemport_id,
                priority=logical_flow.priority,
                classifier=self.mk_classifier(classifier),
                action=self.mk_action(action))

        self.add_flow_to_device(flow, logical_flow)

    def add_dhcp_trap(self, intf_id, onu_id, classifier, action, logical_flow):

        self.log.debug('add dhcp upstream trap', classifier=classifier,
                       action=action)

        action.clear()
        action['trap_to_host'] = True
        classifier['pkt_tag_type'] = 'single_tag'
        classifier.pop('vlan_vid', None)

        gemport_id = platform.mk_gemport_id(intf_id, onu_id)
        flow_id = platform.mk_flow_id(intf_id, onu_id, DHCP_FLOW_INDEX)

        upstream_flow = openolt_pb2.Flow(
            onu_id=onu_id, flow_id=flow_id, flow_type="upstream",
            access_intf_id=intf_id, gemport_id=gemport_id,
            priority=logical_flow.priority,
            classifier=self.mk_classifier(classifier),
            action=self.mk_action(action))

        self.add_flow_to_device(upstream_flow, logical_flow)


        # FIXME - ONOS should send explicit upstream and downstream
        #         exact dhcp trap flow.

        downstream_logical_flow = copy.deepcopy(logical_flow)
        for oxm_field in downstream_logical_flow.match.oxm_fields:
            if oxm_field.ofb_field.type == OFPXMT_OFB_IN_PORT:
                oxm_field.ofb_field.port = 128

        classifier['udp_src'] = 67
        classifier['udp_dst'] = 68
        classifier['pkt_tag_type'] = 'double_tag'
        action.pop('push_vlan', None)

        flow_id = platform.mk_flow_id(intf_id, onu_id,
                                      DHCP_DOWNLINK_FLOW_INDEX)

        downstream_flow = openolt_pb2.Flow(
            onu_id=onu_id, flow_id=flow_id, flow_type="downstream",
            access_intf_id=intf_id, network_intf_id=0, gemport_id=gemport_id,
            priority=logical_flow.priority, classifier=self.mk_classifier(
                classifier),
            action=self.mk_action(action))


        self.add_flow_to_device(downstream_flow, downstream_logical_flow)

    def add_eapol_flow(self, intf_id, onu_id, logical_flow,
                       uplink_eapol_id=EAPOL_FLOW_INDEX,
                       downlink_eapol_id=EAPOL_DOWNLINK_FLOW_INDEX,
                       vlan_id=DEFAULT_MGMT_VLAN):

        downlink_classifier = {}
        downlink_classifier['eth_type'] = EAP_ETH_TYPE
        downlink_classifier['pkt_tag_type'] = 'single_tag'
        downlink_classifier['vlan_vid'] = vlan_id

        downlink_action = {}
        downlink_action['push_vlan'] = True
        downlink_action['vlan_vid'] = vlan_id

        uplink_classifier = {}
        uplink_classifier['eth_type'] = EAP_ETH_TYPE
        uplink_classifier['pkt_tag_type'] = 'single_tag'
        uplink_classifier['vlan_vid'] = vlan_id

        uplink_action = {}
        uplink_action['trap_to_host'] = True

        gemport_id = platform.mk_gemport_id(intf_id, onu_id)

        # Add Upstream EAPOL Flow.

        uplink_flow_id = platform.mk_flow_id(intf_id, onu_id, uplink_eapol_id)

        upstream_flow = openolt_pb2.Flow(
            onu_id=onu_id, flow_id=uplink_flow_id, flow_type="upstream",
            access_intf_id=intf_id, gemport_id=gemport_id,
            priority=logical_flow.priority,
            classifier=self.mk_classifier(uplink_classifier),
            action=self.mk_action(uplink_action))

        logical_flow = copy.deepcopy(logical_flow)
        logical_flow.match.oxm_fields.extend(fd.mk_oxm_fields([fd.vlan_vid(
            vlan_id | 0x1000)]))
        logical_flow.match.type = OFPMT_OXM

        self.add_flow_to_device(upstream_flow, logical_flow)

        # Add Downstream EAPOL Flow.
        downlink_flow_id = platform.mk_flow_id(intf_id, onu_id,
                                               downlink_eapol_id)

        downstream_flow = openolt_pb2.Flow(
            onu_id=onu_id, flow_id=downlink_flow_id, flow_type="downstream",
            access_intf_id=intf_id, gemport_id=gemport_id,
            priority=logical_flow.priority,
            classifier=self.mk_classifier(downlink_classifier),
            action=self.mk_action(downlink_action))

        downstream_logical_flow = ofp_flow_stats(id=logical_flow.id,
             cookie=logical_flow.cookie, table_id=logical_flow.table_id,
             priority=logical_flow.priority, flags=logical_flow.flags)

        downstream_logical_flow.match.oxm_fields.extend(fd.mk_oxm_fields([
            fd.in_port(fd.get_out_port(logical_flow)),
            fd.eth_type(EAP_ETH_TYPE), fd.vlan_vid(vlan_id | 0x1000)]))
        downstream_logical_flow.match.type = OFPMT_OXM

        downstream_logical_flow.instructions.extend(
            fd.mk_instructions_from_actions([fd.output(
            platform.mk_uni_port_num(intf_id, onu_id))]))

        self.add_flow_to_device(downstream_flow, downstream_logical_flow)



    def mk_classifier(self, classifier_info):

        classifier = openolt_pb2.Classifier()

        if 'eth_type' in classifier_info:
            classifier.eth_type = classifier_info['eth_type']
        if 'ip_proto' in classifier_info:
            classifier.ip_proto = classifier_info['ip_proto']
        if 'vlan_vid' in classifier_info:
            classifier.o_vid = classifier_info['vlan_vid']
        if 'metadata' in classifier_info:
            classifier.i_vid = classifier_info['metadata']
        if 'vlan_pcp' in classifier_info:
            classifier.o_pbits = classifier_info['vlan_pcp']
        if 'udp_src' in classifier_info:
            classifier.src_port = classifier_info['udp_src']
        if 'udp_dst' in classifier_info:
            classifier.dst_port = classifier_info['udp_dst']
        if 'ipv4_dst' in classifier_info:
            classifier.dst_ip = classifier_info['ipv4_dst']
        if 'ipv4_src' in classifier_info:
            classifier.src_ip = classifier_info['ipv4_src']
        if 'pkt_tag_type' in classifier_info:
            if classifier_info['pkt_tag_type'] == 'single_tag':
                classifier.pkt_tag_type = 'single_tag'
            elif classifier_info['pkt_tag_type'] == 'double_tag':
                classifier.pkt_tag_type = 'double_tag'
            elif classifier_info['pkt_tag_type'] == 'untagged':
                classifier.pkt_tag_type = 'untagged'
            else:
                classifier.pkt_tag_type = 'none'

        return classifier

    def mk_action(self, action_info):
        action = openolt_pb2.Action()

        if 'pop_vlan' in action_info:
            action.o_vid = action_info['vlan_vid']
            action.cmd.remove_outer_tag = True
        elif 'push_vlan' in action_info:
            action.o_vid = action_info['vlan_vid']
            action.cmd.add_outer_tag = True
        elif 'trap_to_host' in action_info:
            action.cmd.trap_to_host = True
        else:
            self.log.info('Invalid-action-field', action_info=action_info)
            return
        return action

    def is_eap_enabled(self, intf_id, onu_id):
        flows = self.logical_flows_proxy.get('/').items

        for flow in flows:
            eap_flow = False
            eap_intf_id = None
            eap_onu_id = None
            for field in fd.get_ofb_fields(flow):
                if field.type == fd.ETH_TYPE:
                    if field.eth_type == EAP_ETH_TYPE:
                        eap_flow = True
                if field.type == fd.IN_PORT:
                    eap_intf_id = platform.intf_id_from_uni_port_num(
                        field.port)
                    eap_onu_id = platform.onu_id_from_port_num(field.port)

            if eap_flow:
                self.log.debug('eap flow detected', onu_id=onu_id,
                               intf_id=intf_id, eap_intf_id=eap_intf_id,
                               eap_onu_id=eap_onu_id)
            if eap_flow and intf_id == eap_intf_id and onu_id == eap_onu_id:
                return (True, flow)

        return (False, None)

    def add_flow_to_device(self, flow, logical_flow):
        self.log.debug('pushing flow to device', flow=flow)
        self.stub.FlowAdd(flow)
        self.register_flow(logical_flow, flow)

    def register_flow(self, logical_flow, device_flow):
        self.log.debug('registering flow in device',
                       logical_flow=logical_flow, device_flow=device_flow)
        stored_flow = copy.deepcopy(logical_flow)
        stored_flow.id = self.generate_stored_id(device_flow.flow_id,
                                                 device_flow.flow_type)
        self.log.debug('generated device flow id', id=stored_flow.id,
                       flow_id=device_flow.flow_id,
                       direction=device_flow.flow_type)
        stored_flow.cookie = logical_flow.id
        flows = self.flows_proxy.get('/')
        flows.items.extend([stored_flow])
        self.flows_proxy.update('/', flows)


    def find_next_flow(self, flow):
        table_id = fd.get_goto_table_id(flow)
        metadata = 0
        for field in fd.get_ofb_fields(flow):
            if field.type == fd.METADATA:
                metadata = field.table_metadata
        if table_id is None:
            return None
        flows = self.logical_flows_proxy.get('/').items
        next_flows = []
        for f in flows:
            if f.table_id == table_id:
                #FIXME:
                if fd.get_in_port(f) == fd.get_in_port(flow) and \
                        fd.get_out_port(f) == metadata:

                    next_flows.append(f)


        if len(next_flows) == 0:
            self.log.warning('no next flow found, it may be a timing issue',
                             flow=flow, number_of_flows=len(flows))
            reactor.callLater(5, self.add_flow, flow)
            return None

        next_flows.sort(key=lambda f:f.priority, reverse=True)

        return next_flows[0]

    def update_children_flows(self, device_rules_map):

        for device_id, (flows, groups) in device_rules_map.iteritems():
            if device_id != self.device_id:
                self.root_proxy.update('/devices/{}/flows'.format(device_id),
                                       Flows(items=flows.values()))
                self.root_proxy.update('/devices/{}/flow_groups'.format(
                    device_id), FlowGroups(items=groups.values()))

    def generate_stored_id(self, flow_id, direction):
        if direction == 'upstream':
            self.log.debug('upstream flow, shifting id')
            return 0x1 << 15 | flow_id
        elif direction == 'downstream':
            self.log.debug('downstream flow, not shifting id')
            return flow_id
        else:
            self.log.warn('Unrecognized direction', direction=direction)
            return flow_id

    def decode_stored_id(self, id):
        if id >> 15 == 0x1:
            return (id & 0x7fff, 'upstream')
        else:
            return (id, 'downstream')