# 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 __future__ import absolute_import

import requests
import urllib
from requests.auth import HTTPBasicAuth
from xossynchronizer.steps.syncstep import SyncStep
from xossynchronizer.modelaccessor import SwitchPort, PortInterface, FabricIpAddress, model_accessor

from xosconfig import Config
from multistructlog import create_logger

from helpers import Helpers

log = create_logger(Config().get('logging'))

class SyncFabricPort(SyncStep):
    provides = [SwitchPort]
    observes = [SwitchPort, PortInterface, FabricIpAddress]

    def sync_record(self, model):

        if model.leaf_model_name == "PortInterface":
            log.info("Received update for PortInterface", port=model.port.portId, interface=model)
            return self.sync_record(model.port)

        if model.leaf_model_name == "FabricIpAddress":
            log.info("Received update for FabricIpAddress",
                     port=model.interface.port.portId,
                     interface=model.interface.name,
                     ip=model.ip)
            return self.sync_record(model.interface.port)

        log.info("Adding port %s/%s to onos-fabric" % (model.switch.ofId, model.portId))
        interfaces = []
        for intf in model.interfaces.all():
            i = {
                "name": intf.name,
                "ips": [i.ip for i in intf.ips.all()]
            }
            if intf.vlanUntagged:
                i["vlan-untagged"] = intf.vlanUntagged
            interfaces.append(i)

        # Send port config to onos-fabric netcfg
        data = {
            "ports": {
                "%s/%s" % (model.switch.ofId, model.portId): {
                    "interfaces": interfaces,
                    "hostLearning": {
                        "enabled": model.host_learning
                    }
                }
            }
        }

        log.debug("Port %s/%s data" % (model.switch.ofId, model.portId), data=data)

        onos = Helpers.get_onos(model.switch, self.model_accessor)
        url = 'http://%s:%s/onos/v1/network/configuration/' % (onos.rest_hostname, onos.rest_port)
        r = requests.post(url, json=data, auth=HTTPBasicAuth(onos.rest_username, onos.rest_password))
        if r.status_code != 200:
            log.error(r.text)
            raise Exception("Failed to add port  %s/%s into ONOS" % (model.switch.ofId, model.portId))
        else:
            try:
                log.info("Port %s/%s response" % (model.switch.ofId, model.portId), json=r.json())
            except Exception:
                log.info("Port %s/%s response" % (model.switch.ofId, model.portId), text=r.text)
        # Now set the port's administrative state.
        # TODO(smbaker): See if netcfg allows us to specify the portstate instead of using a separate REST call.
        url = 'http://%s:%s/onos/v1/devices/%s/portstate/%s' % (onos.rest_hostname, onos.rest_port, model.switch.ofId, model.portId)
        data = {"enabled": True if model.admin_state == "enabled" else False}
        log.debug("Sending portstate %s to %s/%s" % (data, model.switch.ofId, model.portId))
        r = requests.post(url, json=data, auth=HTTPBasicAuth(onos.rest_username, onos.rest_password))
        if r.status_code != 200:
            log.error(r.text)
            raise Exception("Failed to set portstate  %s/%s into ONOS" % (model.switch.ofId, model.portId))
        else:
            try:
                log.info("Portstate %s/%s response" % (model.switch.ofId, model.portId), json=r.json())
            except Exception:
                log.info("Portstate %s/%s response" % (model.switch.ofId, model.portId), text=r.text)

    def delete_netcfg_item(self, partial_url, switch, model_accessor):
        onos = Helpers.get_onos(switch, model_accessor)
        url = 'http://%s:%s/onos/v1/network/configuration/ports/%s' % (onos.rest_hostname, onos.rest_port, partial_url)
        r = requests.delete(url, auth=HTTPBasicAuth(onos.rest_username, onos.rest_password))
        if r.status_code != 204:
            log.error(r.text)
            raise Exception("Failed to %s port %s from ONOS" % url)

    def delete_record(self, model):
        if model.leaf_model_name == "PortInterface":
            log.info("Received update for PortInterface", port=model.port.portId, interface=model.name)
            log.info("Removing port interface %s from port %s/%s in onos-fabric" %
                     (model.name, model.port.switch.ofId, model.port.portId))

            # resync the existing interfaces
            return self.sync_record(model.port)

        if model.leaf_model_name == "FabricIpAddress":
            # TODO add unit tests
            log.info(
                "Received update for FabricIpAddress",
                port=model.interface.port.portId,
                interface=model.interface.name,
                ip=model.ip)
            log.info("Removing IP %s from interface %s, on port %s/%s in onos-fabric" %
                     (model.ip, model.interface.name, model.interface.port.switch.ofId, model.interface.port.portId))

            # resync the existing interfaces
            return self.sync_record(model.interface.port)

        log.info("Removing port %s/%s from onos-fabric" % (model.switch.ofId, model.portId))

        key = "%s/%s" % (model.switch.ofId, model.portId)
        key = urllib.quote(key, safe='')

        # deleting the port
        self.delete_netcfg_item(key, model.switch, self.model_accessor)
