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

import requests
from synchronizers.new_base.syncstep import SyncStep, DeferredException
from synchronizers.new_base.modelaccessor import *
from xos.logger import Logger, logging

logger = Logger(level=logging.INFO)

DATAPLANE_IP = "dataPlaneIp"
PREFIX = "prefix"
NEXT_HOP = "nextHop"

class SyncAddressManagerServiceInstance(SyncStep):
    provides=[AddressManagerServiceInstance]
    observes = AddressManagerServiceInstance
    requested_interval=30
       
    def get_fabric_onos_service_internal(self):
        # There will be a ServiceInstanceLink from the FabricService to the Fabric ONOS App
        fs = FabricService.objects.first()
        for link in fs.subscribed_links.all():
            if link.provider_service_instance:
                # cast from ServiceInstance to ONOSApp
                service_instance = link.provider_service_instance.leaf_model
                # cast from Service to ONOSService
                return service_instance.owner.leaf_model

        return None

    def get_fabric_onos_service(self):
        fos = self.get_fabric_onos_service_internal()
        if not fos:
            raise Exception("Fabric ONOS service not found")
        return fos

    def get_node_tag(self, node, tagname):
        tags = Tag.objects.filter(content_type=model_accessor.get_content_type_id(node),
                                  object_id=node.id,
                                  name=tagname)
        if tags:
            return tags[0].value
        else:
            return None

    def fetch_pending(self, deleted):
        # If fetch_pending is being called for delete, then just execute the standard delete logic.
        if deleted:
            return super(SyncAddressManagerServiceInstance, self).fetch_pending(deleted)

        fs = FabricService.objects.first()
        if (not fs) or (not fs.autoconfig):
            logger.info("Not FabricServer or not autoconfig. Returning []");
            return []

        objs = super(SyncAddressManagerServiceInstance, self).fetch_pending(deleted)
        objs = list(objs)

        # Check that each is a valid VSG tenant or instance
        for address_si in objs:
            sub = self.get_subscriber(address_si)
            if sub:
                if not sub.instance:
                    logger.info("Skipping %s because it has no instance" % address_si)
                    objs.remove(address_si)
            else:
                # Maybe the Address is for an instance
                # TODO: tenant_for_instance_id needs to be a real database field
                instance_id = address_si.get_attribute("tenant_for_instance_id")
                if not instance_id:
                    logger.info("Skipping %s because it has no tenant_for_instance_id" % address_si)
                    objs.remove(address_si)
                else:
                    instance = Instance.objects.filter(id=instance_id)[0]
                    if not instance.instance_name:
                        logger.info("Skipping %s because it has no instance.instance_name" % address_si)
                        objs.remove(address_si)

        return objs

    def get_subscriber(self, address_si):
        links = address_si.provided_links.all()
        for link in links:
            if not link.subscriber_service_instance:
                continue
            # cast from ServiceInstance to VSGTEnant or similar
            sub = link.subscriber_service_instance.leaf_model
            # TODO: check here to make sure it's an appropriate type of ServiceInstance ?
            return sub
        return None

    def get_routes_url(self, fos):
        url = 'http://%s:%s/onos/v1/routes' % (fos.rest_hostname, fos.rest_port)

        logger.info("url: %s" % url)
        return url

    def sync_record(self, address_si):
        fos = self.get_fabric_onos_service()

        data = self.map_tenant_to_route(address_si)

        r = self.post_route(fos, data)

        logger.info("Posted %s: status: %s result '%s'" % (address_si, r.status_code, r.text))

    def delete_record(self, address_si):
        pass
        # Disabled for now due to lack of feedback state field
        # self.delete_route(self.get_fabric_onos_service(),  self.map_tenant_to_route(address_si))


    def map_tenant_to_route(self, address_si):
        instance = None
        # Address setup is kind of hacky right now, we'll
        # need to revisit.  The idea is:
        # * Look up the instance corresponding to the address
        # * Look up the node running the instance
        # * Get the "dataPlaneIp" tag, push to the fabric

        sub = self.get_subscriber(address_si)
        if sub:
            instance = sub.instance
        else:
            instance_id = address_si.get_attribute("tenant_for_instance_id")
            instance = Instance.objects.filter(id=instance_id)[0]

        node = instance.node
        dataPlaneIp = self.get_node_tag(node, DATAPLANE_IP)

        if not dataPlaneIp:
            raise DeferredException("No IP found for node %s tenant %s -- skipping" % (str(node), str(address_si)))

        data = {
            PREFIX : "%s/32" % address_si.public_ip,
            NEXT_HOP : dataPlaneIp.split('/')[0]
        }

        return data

    def delete_route(self, fos, route):
        url = self.get_routes_url(fos)

        r = requests.delete(url, json=route, auth=(fos.rest_username, fos.rest_password))

        logger.info("status: %s" % r.status_code)
        logger.info('result: %s' % r.text)

        return r

    def post_route(self, fos, route):
        url = self.get_routes_url(fos)
        return requests.post(url, json=route, auth=(fos.rest_username, fos.rest_password))

