#
# Copyright 2017-present Adtran, Inc.
#
# 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 structlog
from adapters.adtran_common.xpon.gem_port import GemPort
from twisted.internet.defer import inlineCallbacks, returnValue
from pyvoltha.adapters.extensions.omci.omci_me import GemPortNetworkCtpFrame, GemInterworkingTpFrame
from pyvoltha.adapters.extensions.omci.omci_defs import ReasonCodes


class OnuGemPort(GemPort):
    """
    Adtran ONU specific implementation
    """
    UPSTREAM = 1
    DOWNSTREAM = 2
    BIDIRECTIONAL = 3

    def __init__(self, handler, gem_data, alloc_id, tech_profile_id,
                 uni_id, entity_id,
                 multicast=False, traffic_class=None, is_mock=False):
        gem_id = gem_data['gemport-id']
        self.log = structlog.get_logger(device_id=handler.device_id, gem_id=gem_id)
        encryption = gem_data['encryption']

        super(OnuGemPort, self).__init__(gem_id, alloc_id, uni_id,
                                         tech_profile_id,
                                         encryption=encryption,
                                         multicast=multicast,
                                         traffic_class=traffic_class,
                                         handler=handler,
                                         is_mock=is_mock)
        try:
            self._gem_data = gem_data
            self._entity_id = entity_id
            self._tcont_entity_id = None
            self._interworking = False
            self.uni_id = gem_data['uni-id']
            self.direction = gem_data.get('direction', OnuGemPort.BIDIRECTIONAL)

            # IEEE 802.1p Mapper ME (#130) related parameters
            self._pbit_map = None
            self.pbit_map = gem_data.get('pbit-map', '0b00000011')

            # Upstream priority queue ME (#277) related parameters
            self.priority_q = gem_data.get('priority-q', 3)

            self._max_q_size = None
            self.max_q_size = gem_data.get('max-q-size', 'auto')

            self.weight = gem_data.get('weight', 8)

            self._discard_config = None
            self.discard_config = gem_data.get('discard-config',  None)

            self._discard_policy = None
            self.discard_policy = gem_data.get('discard-policy', 'TailDrop')

            # Traffic scheduler ME (#278) related parameters
            self._scheduling_policy = None
            self.scheduling_policy = gem_data.get('scheduling-policy', 'WRR')

        except Exception as _e:
            raise

    @property
    def entity_id(self):
        return self._entity_id

    @property
    def discard_config(self):
        return self._discard_config

    @discard_config.setter
    def discard_config(self, discard_config):
        assert isinstance(discard_config, dict), "discard-config not dict"
        assert 'max-probability' in discard_config, "max-probability missing"
        assert 'max-threshold' in discard_config, "max-hreshold missing"
        assert 'min-threshold' in discard_config, "min-threshold missing"
        self._discard_config = discard_config

    @property
    def discard_policy(self):
        self.log.debug('function-entry')
        return self._discard_policy

    @discard_policy.setter
    def discard_policy(self, discard_policy):
        dp = ("TailDrop", "WTailDrop", "RED", "WRED")
        assert (isinstance(discard_policy, str))
        assert (discard_policy in dp)
        self._discard_policy = discard_policy

    @property
    def max_q_size(self):
        return self._max_q_size

    @max_q_size.setter
    def max_q_size(self, max_q_size):
        if isinstance(max_q_size, str):
            assert (max_q_size == "auto")
        else:
            assert (isinstance(max_q_size, int))

        self._max_q_size = max_q_size

    @property
    def pbit_map(self):
        return self._pbit_map

    @pbit_map.setter
    def pbit_map(self, pbit_map):
        assert (isinstance(pbit_map, str))
        assert (len(pbit_map[2:]) == 8)  # Example format of pbit_map: "0b00000101"
        try:
            _ = int(pbit_map[2], 2)
        except ValueError:
            raise Exception("pbit_map-not-binary-string-{}".format(pbit_map))

        # remove '0b'
        self._pbit_map = pbit_map[2:]

    @property
    def scheduling_policy(self):
        return self._scheduling_policy

    @scheduling_policy.setter
    def scheduling_policy(self, scheduling_policy):
        sp = ("WRR", "StrictPriority")
        assert (isinstance(scheduling_policy, str))
        assert (scheduling_policy in sp)
        self._scheduling_policy = scheduling_policy

    @property
    def in_hardware(self):
        return self._tcont_entity_id is not None and self._interworking

    @staticmethod
    def create(handler, gem_data, alloc_id, tech_profile_id, uni_id, entity_id):
        return OnuGemPort(handler, gem_data, alloc_id,
                          tech_profile_id, uni_id, entity_id)

    @property
    def tcont(self):
        """ Get the associated TCONT object """
        return self._handler.pon_port.tconts.get(self.alloc_id)

    @inlineCallbacks
    def add_to_hardware(self, omci,
                        tcont_entity_id,
                        ieee_mapper_service_profile_entity_id,
                        gal_enet_profile_entity_id):
        if self._is_mock:
            returnValue('mock')

        self.log.debug('add-to-hardware', gem_id=self.gem_id,
                       gem_entity_id=self.entity_id,
                       tcont_entity_id=tcont_entity_id,
                       ieee_mapper_service_profile_entity_id=ieee_mapper_service_profile_entity_id,
                       gal_enet_profile_entity_id=gal_enet_profile_entity_id)

        if self._tcont_entity_id is not None and self._tcont_entity_id != tcont_entity_id:
            raise KeyError('GEM Port already assigned to TCONT: {}'.format(self._tcont_entity_id))

        results = None
        if self._tcont_entity_id is None:
            try:
                direction = "downstream" if self.multicast else "bi-directional"
                assert not self.multicast, 'MCAST is not supported yet'

                frame = GemPortNetworkCtpFrame(
                        self.entity_id,          # same entity id as GEM port
                        port_id=self.gem_id,
                        tcont_id=tcont_entity_id,
                        direction=direction,
                        upstream_tm=0x8000      # TM ID, 32768 unique ID set in TD set  TODO: Parameterize
                                                # This is Priority Queue ME with this entity ID
                                                # and the ME's related port value is 0x01.00.0007
                                                # which is  slot=0x01, tcont# = 0x00, priority= 0x0007
                ).create()
                results = yield omci.send(frame)

                status = results.fields['omci_message'].fields['success_code']
                error_mask = results.fields['omci_message'].fields['parameter_error_attributes_mask']
                self.log.debug('create-gem-port-network-ctp', status=status, error_mask=error_mask)

                if status == ReasonCodes.Success or status == ReasonCodes.InstanceExists:
                    self._tcont_entity_id = tcont_entity_id
                else:
                    raise Exception('GEM Port create failed with status: {}'.format(status))

            except Exception as e:
                self.log.exception('gemport-create', e=e)
                raise

        if not self._interworking:
            try:
                extra = {'gal_loopback_configuration': 0}   # No loopback

                frame = GemInterworkingTpFrame(
                    self.entity_id,          # same entity id as GEM port
                    gem_port_network_ctp_pointer=self.entity_id,
                    interworking_option=5,                             # IEEE 802.1
                    service_profile_pointer=ieee_mapper_service_profile_entity_id,
                    interworking_tp_pointer=0x0,
                    pptp_counter=1,
                    gal_profile_pointer=gal_enet_profile_entity_id,
                    attributes=extra
                ).create()
                results = yield omci.send(frame)

                status = results.fields['omci_message'].fields['success_code']
                error_mask = results.fields['omci_message'].fields['parameter_error_attributes_mask']
                self.log.debug('create-gem-interworking-tp', status=status, error_mask=error_mask)

                if status == ReasonCodes.Success or status == ReasonCodes.InstanceExists:
                    self._interworking = True
                else:
                    raise Exception('GEM Interworking create failed with status: {}'.format(status))

            except Exception as e:
                self.log.exception('interworking-create', e=e)
                raise

        returnValue(results)

    @inlineCallbacks
    def remove_from_hardware(self, omci):
        if self._is_mock:
            returnValue('mock')

        self.log.debug('remove-from-hardware',  gem_id=self.gem_id)

        results = None
        if self._interworking:
            try:
                frame = GemInterworkingTpFrame(self.entity_id).delete()
                results = yield omci.send(frame)
                status = results.fields['omci_message'].fields['success_code']
                self.log.debug('delete-gem-interworking-tp', status=status)

                if status == ReasonCodes.Success:
                    self._interworking = False

            except Exception as e:
                self.log.exception('interworking-delete', e=e)
                raise

        if self._tcont_entity_id is not None:
            try:
                frame = GemPortNetworkCtpFrame(self.entity_id).delete()
                results = yield omci.send(frame)

                status = results.fields['omci_message'].fields['success_code']
                self.log.debug('delete-gem-port-network-ctp', status=status)

                if status == ReasonCodes.Success:
                    self._tcont_entity_id = None

            except Exception as e:
                self.log.exception('gemport-delete', e=e)
                raise

        returnValue(results)
