#
# 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.
#

from __future__ import absolute_import
import structlog
from pyvoltha.adapters.extensions.omci.omci_entities import OntG, PriorityQueueG, Tcont
from pyvoltha.adapters.extensions.omci.omci_me import MacBridgePortConfigurationDataFrame, AccessControlRow0, \
    MulticastOperationsProfileFrame, MulticastSubscriberConfigInfoFrame, VlanTaggingFilterDataFrame, \
    ExtendedVlanTaggingOperationConfigurationDataFrame, VlanTaggingOperation
from twisted.internet import reactor
from pyvoltha.adapters.extensions.omci.omci_defs import ReasonCodes, EntityOperations
from pyvoltha.adapters.extensions.omci.tasks.task import Task
from twisted.internet.defer import inlineCallbacks, failure


RC = ReasonCodes
OP = EntityOperations
IGMP_VERSION = 2
RESERVED_VLAN = 4095


class BrcmMcastTask(Task):
    task_priority = 150
    name = "Broadcom Multicast Task"

    def __init__(self, omci_agent, handler, device_id, uni_id, tp_id, vlan_id, dynamic_acl, static_acl, multicast_gem_id ):

        self.log = structlog.get_logger ( device_id=device_id )
        super ( BrcmMcastTask , self ).__init__ ( BrcmMcastTask.name ,
                                                  omci_agent ,
                                                  device_id,
                                                  self.task_priority)
        self._device = omci_agent.get_device ( device_id )
        self._results = None
        self._local_deferred = None
        self._uni_port = handler.uni_ports[uni_id]
        assert self._uni_port.uni_id == uni_id
        #mcast entities IDs
        self._mcast_operation_profile_id = handler.pon_port.mac_bridge_port_ani_entity_id + tp_id
        self._mcast_sub_conf_info_id = self._mcast_operation_profile_id + tp_id
        self._mac_bridge_service_profile_entity_id = handler.mac_bridge_service_profile_entity_id
        self._mac_bridge_configuration_data_id =self._mac_bridge_service_profile_entity_id +\
                                                self._uni_port.mac_bridge_port_num
        self._ieee_mapper_service_profile_entity_id = \
            handler.pon_port.ieee_mapper_service_profile_entity_id
        self._gal_enet_profile_entity_id = \
            handler.gal_enet_profile_entity_id
        # using for multicast operations profile and multicast subscriber config info
        self._set_igmp_function = 0
        self._set_immediate_leave = False
        self._set_vlan_id = vlan_id
        # dynamic_access_control_list , static_access_control_list and multicast_gem_id
        self._dynamic_acl= dynamic_acl
        self._static_acl= static_acl
        self._mcast_gem_id= multicast_gem_id
        self._uni_port = handler.uni_ports[uni_id]
        assert self._uni_port.uni_id == uni_id
        # gem_port list
        self._gem_ports = []
        for gem_port in list(handler.pon_port.gem_ports.values()):
            if gem_port.uni_id is not None and gem_port.uni_id != self._uni_port.uni_id: continue
            self._gem_ports.append(gem_port)

        self._tcont_list=[]
        for gem_port in self._gem_ports:
            self._tcont_list.append(gem_port.tcont)
        self.tcont_me_to_queue_map = dict()
        self.uni_port_to_queue_map = dict()

        self._set_me_type = 0
        self._set_interworking_option = 0
        self._store_tcont_list()

    def cancel_deferred(self):
        super ( BrcmMcastTask , self ).cancel_deferred ()
        d , self._local_deferred = self._local_deferred , None
        try:
            if d is not None and not d.called:
                d.cancel ()
        except:
            pass

    def start(self):
        super ( BrcmMcastTask , self ).start ()
        self._local_deferred = reactor.callLater ( 0 , self.perform_multicast )

    @inlineCallbacks
    def perform_multicast(self):
        self.log.debug('performing-multicast', device_id=self._device._device_id, uni_id=self._uni_port.uni_id,
                        vlan_id=self._set_vlan_id, multicast_gem_id=self._mcast_gem_id)

        try:
            # create gem port and use tcont
            yield self._create_gem_ports()

            # create multicast operation profile
            yield self._create_mcast_operation_profile()

            # set multicast operation profile
            yield self._set_mcast_operation_profile()

            # create multicast subscriber config data
            yield self._create_mcast_subscriber_conf_info()

            # create mac bridge port configuration data
            yield self._create_mac_bridge_configuration_data()

            # create vlan filtering entity
            yield self._create_vlan_tagging_filter_data()

            # set vlan filtering entity
            yield self._set_vlan_tagging_filter_data()

            self.deferred.callback ( self )
        except Exception as e:
            self.log.exception ( 'multicast exception' , e=e )
            self.deferred.errback ( failure.Failure ( e ) )

    @inlineCallbacks
    def _create_gem_ports(self):
        omci_cc = self._device.omci_cc
        try:
            tcont = None
            self.log.debug("tcont-list", _tcont_list=self._tcont_list)
            for gem_tcont in self._tcont_list:
                if gem_tcont.entity_id is not None:
                    tcont=gem_tcont
            for gem_port in self._gem_ports:
                gem_port_tcont= gem_port.tcont
                if gem_port_tcont is not None and gem_port_tcont.entity_id is not None:
                    tcont = gem_port.tcont
                ul_prior_q_entity_id = \
                    self.tcont_me_to_queue_map[tcont.entity_id][gem_port.priority_q]
                self.log.debug("ul_prior_q_entity_id", ul_priority=ul_prior_q_entity_id)

                dl_prior_q_entity_id = \
                    self.uni_port_to_queue_map[self._uni_port.entity_id][gem_port.priority_q]
                if ul_prior_q_entity_id is not None and dl_prior_q_entity_id is not None:
                    if gem_port.direction == 'downstream' and gem_port.gem_id == self._mcast_gem_id:
                        results = yield gem_port.add_to_hardware ( omci=omci_cc ,
                                                                   tcont_entity_id=tcont.entity_id ,
                                                                   ieee_mapper_service_profile_entity_id=self._ieee_mapper_service_profile_entity_id +
                                                                                                         self._uni_port.mac_bridge_port_num ,
                                                                   gal_enet_profile_entity_id=self._gal_enet_profile_entity_id ,
                                                                   ul_prior_q_entity_id=ul_prior_q_entity_id ,
                                                                   dl_prior_q_entity_id=dl_prior_q_entity_id)
                        self.check_status_and_state ( results , 'assign-gem-port' )
                        pass
        except Exception as e:
            self.log.debug("failed-create-gem-ports-method", e=e)

    def _store_tcont_list(self):
        pq_to_related_port = dict()
        onu_g = self._device.query_mib ( OntG.class_id )
        traffic_mgmt_opt = \
            onu_g.get ( 'attributes' , {} ).get ( 'traffic_management_options' , 0 )
        self.log.debug ( "traffic-mgmt-option" , traffic_mgmt_opt=traffic_mgmt_opt )

        prior_q = self._device.query_mib ( PriorityQueueG.class_id )
        for k , v in prior_q.items():
            self.log.debug("prior-q", k=k, v=v)
            try:
                _ = iter(v)
            except TypeError:
                continue

            if 'instance_id' in v:
                related_port = v['attributes']['related_port']
                pq_to_related_port[k] = related_port

                if v['instance_id'] & 0b1000000000000000:
                    tcont_me = (related_port & 0xffff0000) >> 16
                    if tcont_me not in self.tcont_me_to_queue_map:
                        self.log.debug ( "prior-q-related-port-and-tcont-me" ,
                                         related_port=related_port ,
                                         tcont_me=tcont_me )
                        self.tcont_me_to_queue_map[tcont_me] = list ()

                    self.tcont_me_to_queue_map[tcont_me].append ( k )
                else:
                    uni_port = (related_port & 0xffff0000) >> 16
                    if uni_port == self._uni_port.entity_id:
                        if uni_port not in self.uni_port_to_queue_map:
                            self.log.debug ( "prior-q-related-port-and-uni-port-me" ,
                                             related_port=related_port ,
                                             uni_port_me=uni_port )
                            self.uni_port_to_queue_map[uni_port] = list ()

                        self.uni_port_to_queue_map[uni_port].append ( k )


    @inlineCallbacks
    def _create_mac_bridge_configuration_data(self):
        self.log.debug ( 'starting-create-mac-bridge-conf-data' )
        attributes = dict ( bridge_id_pointer=self._mac_bridge_configuration_data_id,
                            port_num=0xf0,
                            tp_type=6,
                            tp_pointer=self._mcast_gem_id)
        msg = MacBridgePortConfigurationDataFrame ( entity_id=self._mac_bridge_configuration_data_id, attributes=attributes )
        yield self._send_msg ( msg , 'create' , 'create-mac-bridge-port-conf-data' )


    @inlineCallbacks
    def _create_mcast_operation_profile(self):
        self.log.debug ( 'starting-create-mcast-operation-profile' )
        attributes = dict ( igmp_version=IGMP_VERSION , igmp_function=self._set_igmp_function,
                            immediate_leave=self._set_immediate_leave, robustness=0)
        msg = MulticastOperationsProfileFrame ( entity_id=self._mcast_operation_profile_id,
                                                querier_ip_address=0,
                                                query_interval=125,
                                                query_max_response=100,
                                                last_member_query_interval=10,
                                                unauthorized_join_request_behavior=False,
                                                attributes=attributes)
        yield self._send_msg ( msg , 'create' , 'create-multicast-operation-profile')

    @inlineCallbacks
    def _set_mcast_operation_profile(self):
        self.log.debug('starting-set-mcast-operation-profile')
        dynamic_access_control_list_table= AccessControlRow0 (
            set_ctrl=1 ,
            row_part_id=0 ,
            test=0 ,
            row_key=0 ,
            gem_port_id=self._mcast_gem_id,
            vlan_id=self._set_vlan_id,
            src_ip="0.0.0.0",
            dst_ip_start=self._dynamic_acl[0],
            dst_ip_end=self._dynamic_acl[1],
            ipm_group_bw=0

        )
        msg = MulticastOperationsProfileFrame(entity_id=self._mcast_operation_profile_id,
                                              dynamic_access_control_list_table=dynamic_access_control_list_table
                                             )
        yield self._send_msg(msg, 'set', 'set-multicast-operations-profile')

    @inlineCallbacks
    def _create_mcast_subscriber_conf_info(self):
        self.log.debug ( 'creating-multicast-subscriber-config-info' )
        attributes = dict ( me_type=self._set_me_type,
                            multicast_operations_profile_pointer=self._mcast_operation_profile_id )
        msg = MulticastSubscriberConfigInfoFrame ( entity_id=self._uni_port.entity_id, attributes=attributes )
        yield self._send_msg ( msg , 'create' , 'create-multicast-subscriber-config-info' )


    @inlineCallbacks
    def _create_vlan_tagging_filter_data(self):
        self.log.debug('creating-vlan-tagging-filter-data')
        forward_operation = 0x10  # VID investigation
        # When the PUSH VLAN is RESERVED_VLAN (4095), let ONU be transparent
        if self._set_vlan_id == RESERVED_VLAN:
            forward_operation = 0x00  # no investigation, ONU transparent

        # Create bridge ani side vlan filter
        msg = VlanTaggingFilterDataFrame(
            self._mac_bridge_configuration_data_id,  # Entity ID
            vlan_tcis=[self._set_vlan_id],  # VLAN IDs
            forward_operation=forward_operation
        )

        yield self._send_msg(msg, 'create', 'flow-create-vlan-tagging-filter-data')

    @inlineCallbacks
    def _set_vlan_tagging_filter_data(self):
        self.log.debug('setting-vlan-tagging-filter-data')
        forward_operation = 0x10  # VID investigation
        # When the PUSH VLAN is RESERVED_VLAN (4095), let ONU be transparent
        if self._set_vlan_id == RESERVED_VLAN:
            forward_operation = 0x00  # no investigation, ONU transparent

        # Create bridge ani side vlan filter
        msg = VlanTaggingFilterDataFrame(
            self._mac_bridge_configuration_data_id,  # Entity ID
            vlan_tcis=[self._set_vlan_id],  # VLAN IDs
            forward_operation=forward_operation
        )

        yield self._send_msg(msg, 'set', 'flow-set-vlan-tagging-filter-data')


    @inlineCallbacks
    def _send_msg(self , msg , operation , log_comment):
        if operation == 'create':
            frame = msg.create ()
        elif operation == 'set':
            frame = msg.set ()
        else:
            frame = msg.delete ()
        self.log.debug ( 'openomci-msg' , omci_msg=msg )
        self.strobe_watchdog ()
        results = yield self._device.omci_cc.send ( frame )
        self.check_status_and_state ( results , log_comment )

    def check_status_and_state(self , results , operation=''):
        """
        Check the results of an OMCI response.  An exception is thrown
        if the task was cancelled or an error was detected.

        :param results: (OmciFrame) OMCI Response frame
        :param operation: (str) what operation was being performed
        :return: True if successful, False if the entity existed (already created)
        """

        omci_msg = results.fields['omci_message'].fields
        status = omci_msg['success_code']
        error_mask = omci_msg.get ( 'parameter_error_attributes_mask' , 'n/a' )
        failed_mask = omci_msg.get ( 'failed_attributes_mask' , 'n/a' )
        unsupported_mask = omci_msg.get ( 'unsupported_attributes_mask' , 'n/a' )

        self.log.debug ( "OMCI Result: %s" , operation , omci_msg=omci_msg ,
                         status=status , error_mask=error_mask ,
                         failed_mask=failed_mask , unsupported_mask=unsupported_mask )

        if status == RC.Success:
            self.strobe_watchdog ()
            return True

        elif status == RC.InstanceExists:
            return False
