# 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 enum import Enum
from twisted.internet import reactor
from twisted.internet.defer import inlineCallbacks, returnValue, succeed

from voltha.protos.common_pb2 import OperStatus, AdminState


class AdtnPort(object):
    """
    A class similar to the 'Port' class in the VOLTHA
    """
    class State(Enum):
        INITIAL = 0  # Created and initialization in progress
        RUNNING = 1  # PON port contacted, ONU discovery active
        STOPPED = 2  # Disabled
        DELETING = 3  # Cleanup

    def __init__(self, parent, **kwargs):
        assert parent, 'parent is None'
        assert 'port_no' in kwargs, 'Port number not found'

        self.log = structlog.get_logger(device_id=parent.device_id)

        self._parent = parent
        self._port_no = kwargs.get('port_no')

        # Set the following in your derived class.  These names are used in
        # various ways.  Typically, the physical port name will be used during
        # device handler conversations with the hardware (REST, NETCONF, ...)
        # while the logical port name is what the outside world (ONOS, SEBA, ...)
        # uses.  All ports have a physical port name, but only ports exposed through
        # VOLTHA as a logical port will have a logical port name

        self._physical_port_name = None
        self._logical_port_name = None
        self._label = None
        self._port = None

        self.sync_tick = 20.0
        self.sync_deferred = None  # For sync of PON config to hardware

        # TODO: Deprecate 'enabled' and use admin_state instead may want initial to always be
        # disabled and then in derived classes, set it in the 'reset' method called on startup.
        if parent.xpon_support:
            self._enabled = not parent.xpon_support
            self._admin_state = AdminState.DISABLED
        else:
            self._enabled = not parent.xpon_support
            self._admin_state = AdminState.ENABLED

        self._oper_status = OperStatus.DISCOVERED
        self._state = AdtnPort.State.INITIAL

        self.deferred = None  # General purpose

        # Statistics
        self.rx_packets = 0
        self.rx_bytes = 0
        self.tx_packets = 0
        self.tx_bytes = 0
        self.timestamp = 0

    def __del__(self):
        self.stop()

    def get_port(self):
        """
        Get the VOLTHA PORT object for this port
        :return: VOLTHA Port object
        """
        raise NotImplementedError('Add to your derived class')

    @property
    def port_no(self):
        return self._port_no

    @property
    def intf_id(self):
        return self.port_no

    @property
    def physical_port_name(self):
        return self._physical_port_name

    @property
    def logical_port_name(self):
        return self._logical_port_name

    @property                           # For backwards compatibility
    def name(self):
        return self._logical_port_name

    @property
    def state(self):
        return self._state

    @state.setter
    def state(self, value):
        self._state = value

    @property
    def olt(self):
        return self._parent

    @property
    def admin_state(self):
        return self._admin_state

    @admin_state.setter
    def admin_state(self, value):
        if self._admin_state != value:
            self._admin_state = value
            if self._admin_state == AdminState.ENABLED:
                self.start()
            else:
                self.stop()
    @property
    def enabled(self):
        return self._admin_state == AdminState.ENABLED

    @enabled.setter
    def enabled(self, value):
        assert isinstance(value, bool), 'enabled is a boolean'
        self.admin_state = AdminState.ENABLED if value else AdminState.DISABLED

    @property
    def oper_status(self):
        return self._oper_status

    @property
    def adapter_agent(self):
        return self.olt.adapter_agent

    def get_logical_port(self):
        """
        Get the VOLTHA logical port for this port. For PON ports, a logical port
        is not currently created, so always return None

        :return: VOLTHA logical port or None if not supported
        """
        return None

    def cancel_deferred(self):
        d1, self.deferred = self.deferred, None
        d2, self.sync_deferred = self.sync_deferred, None

        for d in [d1, d2]:
            try:
                if d is not None and not d.called:
                    d.cancel()
            except Exception:
                pass

    def _update_adapter_agent(self):
        raise NotImplementedError('Add to your derived class')

    def start(self):
        """
        Start/enable this PON and start ONU discover
        """
        if self.state == AdtnPort.State.RUNNING:
            return succeed('Running')

        self.log.info('start-port')

        self.cancel_deferred()
        self.state = AdtnPort.State.INITIAL
        self._oper_status = OperStatus.ACTIVATING
        self._enabled = True

        # Do the rest of the startup in an async method
        self.deferred = reactor.callLater(0.5, self.finish_startup)
        self._update_adapter_agent()

        return succeed('Scheduled')

    def finish_startup(self):
        if self.state == AdtnPort.State.INITIAL:
            self.log.debug('final-startup')

            # If here, initial settings were successfully written to hardware

            self._enabled = True
            self._admin_state = AdminState.ENABLED
            self._oper_status = OperStatus.ACTIVE  # TODO: is this correct, how do we tell GRPC
            self.state = AdtnPort.State.RUNNING

            self.sync_deferred = reactor.callLater(self.sync_tick,
                                                   self.sync_hardware)
            self._update_adapter_agent()

    @inlineCallbacks
    def stop(self):
        if self.state == AdtnPort.State.STOPPED:
            self.log.debug('already stopped')
            returnValue('Stopped')

        self.log.info('stopping')
        try:
            self.cancel_deferred()
            self._enabled = False
            self._admin_state = AdminState.DISABLED
            self._oper_status = OperStatus.UNKNOWN
            self._update_adapter_agent()

            self.state = AdtnPort.State.STOPPED

            self.sync_deferred = reactor.callLater(self.sync_tick,
                                                   self.sync_hardware)

            self.deferred = self.finish_stop()
            yield self.deferred

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

        returnValue('Stopped')

    def finish_stop(self):
        pass   # Add to your derived class if needed

    def restart(self):
        if self.state == AdtnPort.State.RUNNING or self.state == AdtnPort.State.STOPPED:
            start_it = (self.state == AdtnPort.State.RUNNING)
            self.state = AdtnPort.State.INITIAL
            return self.start() if start_it else self.stop()
        return succeed('nop')

    def delete(self):
        """
        Parent device is being deleted. Do not change any config but
        stop all polling
        """
        self.log.info('Deleting')
        self.state = AdtnPort.State.DELETING
        self.cancel_deferred()

    def sync_hardware(self):
        raise NotImplementedError('Add to your derived class')

# TODO: Continue to consolidate port functionality
