
# 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 synchronizers.new_base.modelaccessor import *
from synchronizers.new_base.policy import Policy

class VOLTTenantPolicy(Policy):
    model_name = "VOLTTenant"

    def handle_create(self, tenant):
        return self.handle_update(tenant)

    def handle_update(self, tenant):
        self.manage_vsg(tenant)
        self.manage_subscriber(tenant)
        self.cleanup_orphans(tenant)

    def handle_delete(self, tenant):
        if tenant.vcpe:
            tenant.vcpe.delete()

    def manage_vsg(self, tenant):
        # Each VOLT object owns exactly one VCPE object

        if tenant.deleted:
            self.logger.info("MODEL_POLICY: volttenant %s deleted, deleting vsg" % tenant)
            return

        # Check to see if the wrong s-tag is set. This can only happen if the
        # user changed the s-tag after the VoltTenant object was created.
        if tenant.vcpe and tenant.vcpe.instance:
            s_tags = Tag.objects.filter(content_type=tenant.vcpe.instance.self_content_type_id,
                                        object_id=tenant.vcpe.instance.id, name="s_tag")
            if s_tags and (s_tags[0].value != str(tenant.s_tag)):
                self.logger.info("MODEL_POLICY: volttenant %s s_tag changed, deleting vsg" % tenant)
                tenant.vcpe.delete()

        if tenant.vcpe is None:
            vsgServices = VSGService.objects.all()
            if not vsgServices:
                raise XOSConfigurationError("No VSG Services available")

            self.logger.info("MODEL_POLICY: volttenant %s creating vsg" % tenant)

            vcpe = VSGTenant(owner=vsgServices[0])
            vcpe.creator = tenant.creator
            vcpe.save()
            link = ServiceInstanceLink(provider_service_instance = vcpe, subscriber_service_instance = tenant)
            link.save()

    def manage_subscriber(self, tenant):
        # check for existing link to a root
        links = tenant.provided_links.all()
        for link in links:
            roots = CordSubscriberRoot.objects.filter(id = link.subscriber_service_instance.id)
            if roots:
                return

        subs = CordSubscriberRoot.objects.filter(service_specific_id = tenant.service_specific_id)
        if subs:
            self.logger.info("MODEL_POLICY: volttenant %s using existing subscriber root" % tenant)
            sub = subs[0]
        else:
            self.logger.info("MODEL_POLICY: volttenant %s creating new subscriber root" % tenant)
            sub = CordSubscriberRoot(service_specific_id = tenant.service_specific_id,
                                     name = "autogenerated-for-vOLT-%s" % tenant.id)
            sub.save()

        link = ServiceInstanceLink(provider_service_instance = tenant, subscriber_service_instance = sub)
        link.save()

    def cleanup_orphans(self, tenant):
        # ensure vOLT only has one vCPE
        cur_vcpe = tenant.vcpe

        links = tenant.subscribed_links.all()
        for link in links:
            vsgs = VSGTenant.objects.filter(id = link.provider_service_instance.id)
            for vsg in vsgs:
                if (not cur_vcpe) or (vsg.id != cur_vcpe.id):
                    vsg.delete()
