# Copyright 2017-present Open Networking Foundation
#
# 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 xossynchronizer.steps.syncstep import DeferredException

class TtHelpers():
    @staticmethod
    def validate_onu(model_accessor, log, tt_si):
        """
        This method validate an ONU against the whitelist and set the appropriate state.
        It's expected that the deferred exception is managed in the caller method,
        for example a model_policy or a sync_step.

        :param tt_si: TtWorkflowDriverServiceInstance
        :return: [boolean, string]
        """

        oss_service = tt_si.owner.leaf_model

        # See if there is a matching entry in the whitelist.
        matching_entries = model_accessor.TtWorkflowDriverWhiteListEntry.objects.filter(
            owner_id=oss_service.id,
        )
        matching_entries = [e for e in matching_entries if e.serial_number.lower() == tt_si.serial_number.lower()]

        if len(matching_entries) == 0:
            log.warn("ONU not found in whitelist", object=str(tt_si), serial_number=tt_si.serial_number, **tt_si.tologdict())
            return [False, "ONU not found in whitelist"]

        whitelisted = matching_entries[0]
        try:
            pon_port = model_accessor.ONUDevice.objects.get(serial_number=tt_si.serial_number).pon_port
        except IndexError:
            raise DeferredException("ONU device %s is not know to XOS yet" % tt_si.serial_number)

        if pon_port.port_no != whitelisted.pon_port_id or tt_si.of_dpid != whitelisted.device_id:
            log.warn("ONU disable as location don't match",
                     object=str(tt_si),
                     serial_number=tt_si.serial_number,
                     pon_port=pon_port.port_no,
                     whitelisted_pon_port=whitelisted.pon_port_id,
                     device_id=tt_si.of_dpid,
                     whitelisted_device_id=whitelisted.device_id,
                     **tt_si.tologdict())
            return [False, "ONU activated in wrong location"]

        return [True, "ONU has been validated"]

    @staticmethod
    def get_onu_sn(model_accessor, log, event):
        olt_service = model_accessor.VOLTService.objects.first()
        onu_sn = olt_service.get_onu_sn_from_openflow(event["deviceId"], event["portNumber"])
        if not onu_sn or onu_sn is None:
            log.exception("Cannot find onu serial number for this event", kafka_event=event)
            raise Exception("Cannot find onu serial number for this event")

        return onu_sn

    @staticmethod
    def get_si_by_sn(model_accessor, log, serial_number):
        try:
            return model_accessor.TtWorkflowDriverServiceInstance.objects.get(serial_number=serial_number)
        except IndexError:
            log.exception("Cannot find tt-workflow-driver service instance for this serial number", serial_number=serial_number)
            raise Exception("Cannot find tt-workflow-driver service instance for this serial number %s", serial_number)