# 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.model_policies.model_policy_tenantwithcontainer import Policy
from synchronizers.new_base.exceptions import *

from xosconfig import Config
from multistructlog import create_logger

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

blueprints = Config().get('blueprints')


def service_of_service_instance(si):
    if si.endswith('Tenant'):
        return si[:-len('Tenant')] + 'Service'
    elif si.endswith('ServiceInstance'):
        return si[:-len('ServiceInstance')] + 'Service'
    else:
        raise Exception(
            'Could not translate service instance into service: %s' % si)


class VEPCServiceInstancePolicy(Policy):
    model_name = "VEPCServiceInstance"

    def __init__(self):
        self.in_memory_instances = []
        self.network_map = {}

        super(VEPCServiceInstancePolicy, self).__init__()

    """TODO: Update the following to not be service-specific
       This code assumes there is only one vendor installed
    """

    def configure_service_instance(self, service_instance):
        if service_instance.leaf_model_name == 'VSPGWUTenant':
            vendor = VSPGWUVendor.objects.first()
            if not vendor:
                raise Exception('No VSPGWU vendors')
            service_instance.vspgwu_vendor = vendor
            service_instance.invalidate_cache('vspgwu_vendor')
        elif service_instance.leaf_model_name == 'VSPGWCTenant':
            vendor = VSPGWCVendor.objects.first()
            if not vendor:
                raise Exception('No VSPGWC vendors')
            service_instance.vspgwc_vendor = vendor
            service_instance.invalidate_cache('vspgwc_vendor')
        elif service_instance.leaf_model_name == 'VMMETenant':
            vendor = VMMEVendor.objects.first()
            if not vendor:
                raise Exception('No VMME vendors')
            service_instance.vmme_vendor = vendor
            service_instance.invalidate_cache('vmme_vendor')
        elif service_instance.leaf_model_name == 'VHSSTenant':
            vendor = VHSSVendor.objects.first()
            if not vendor:
                raise Exception('No VHSS vendors')
            service_instance.vhss_vendor = vendor
            service_instance.invalidate_cache('vhss_vendor')
        elif service_instance.leaf_model_name == 'HSSDBServiceInstance':
            vendor = HSSDBVendor.objects.first()
            if not vendor:
                raise Exception('No HSSDB vendors')
            service_instance.hssdb_vendor = vendor
            service_instance.invalidate_cache('hssdb_vendor')

    def child_service_instance_from_name(self, name):
        service_instances = self.obj.child_serviceinstances.all()
        service_instances.extend(self.in_memory_instances)

        try:
            service_instance = next(
                s for s in service_instances if s.leaf_model_name == name)
        except StopIteration:
            service_instance = None

        return service_instance

    def get_service_for_service_instance(self, si):
        service = service_of_service_instance(si)
        service_class = getattr(Slice().stub, service)
        service_obj = service_class.objects.first()  # There's only one service object
        return service_obj

    def create_service_instance(self, si, node_label = None):
        service = self.get_service_for_service_instance(si)
        if not service:
            raise Exception('No service object for %s' % service)

        si_class = getattr(Slice().stub, si)
        s = si_class(owner=service, name='epc-%s-%d' %
                     (si.lower(), self.obj.id))
        s.master_serviceinstance = self.obj

        if node_label:
            s.node_label = '%s-%d'%(node_label, self.obj.id)

        s.no_sync = True
        s.no_policy = True
        s.save()

        self.configure_service_instance(s)
        s.save()

        self.in_memory_instances.append(s)
        return s

    def add_networks_to_service(self, service, networks):
        for n in networks:
            net = Network.objects.filter(name=n)[0]
            one_and_only_slice_hopefully = service.slices.all()[0]
            ns_object = NetworkSlice.objects.filter(
                network=net.id, slice=one_and_only_slice_hopefully.id)
            if not ns_object:
                ns_object = NetworkSlice(
                    network=net, slice=one_and_only_slice_hopefully)
                ns_object.save()

    def add_networks_to_service_instance(self, instance, networks):
        for n in networks:
            net = Network.objects.filter(name=n)[0]
            one_and_only_slice_hopefully = instance.owner.slices.all()[0]
            ns_object = NetworkSlice.objects.filter(
                network=net.id, slice=one_and_only_slice_hopefully.id)
            if not ns_object:
                ns_object = NetworkSlice(
                    network=net, slice=one_and_only_slice_hopefully)
                ns_object.save()

    def create_service_instance_with_networks(self, si_name, networks, node_label = None):
        service = self.get_service_for_service_instance(si_name)
        self.add_networks_to_service(service, networks)

        instance = self.child_service_instance_from_name(si_name)

        if not instance:
            instance = self.create_service_instance(si_name, node_label = node_label)

        return instance

    def create_link(self, src_instance, dst_instance):
        src_service = self.get_service_for_service_instance(
            src_instance.leaf_model_name)
        dst_service = self.get_service_for_service_instance(
            dst_instance.leaf_model_name)

        service_dependency = ServiceDependency.objects.filter(
            provider_service_id=dst_service.id, subscriber_service_id=src_service.id)
        if not service_dependency:
            service_dependency = ServiceDependency(
                provider_service=dst_service, subscriber_service=src_service)
            service_dependency.save()

        service_instance_link = ServiceInstanceLink.objects.filter(
            provider_service_instance_id=dst_instance.id, subscriber_service_instance_id=src_instance.id)
        if not service_instance_link:
            service_instance_link = ServiceInstanceLink(
                provider_service_instance=dst_instance, subscriber_service_instance=src_instance)
            service_instance_link.save()

    def recursive_create_instances_and_links(self, blueprint, src, service_instances):
        for node in blueprint:
            k = node['name']
            networks = node.get('networks', [])
            links = node.get('links', [])

            try:
                node_label = node['node_label']
            except KeyError:
                try:
                    node_label = next(l['node_label'] for l in links if l.get('node_label', None))
                except StopIteration:
                    node_label = None

            instance = self.create_service_instance_with_networks(k, networks, node_label = node_label)
            service_instances.append(instance)

            if src:
                self.add_networks_to_service_instance(src, networks)
                self.create_link(src, instance)

            service_instances = self.recursive_create_instances_and_links(links, instance, service_instances)

        return service_instances

    def create_epc_network(self, n):
        network_name = n['name']
        site_name = self.obj.site.login_base

        nets = Network.objects.filter(name=network_name)
        if not nets:
            template_name = n.get('template', 'public')
            try:
                template = NetworkTemplate.objects.filter(name=template_name)[0]
            except:
                raise Exception('Template %s for network %s not found' % (template_name, network_name))

            slice_name = '%s_%s' % (site_name, n['owner'])
            try:
                slice = Slice.objects.filter(name=slice_name)[0]
            except:
                raise Exception('Owner slice %s for network %s not found' % (slice_name, network_name))


            net = Network(name=network_name, subnet=n['subnet'], permit_all_slices=n.get(
                'permit_all_slices', False), template=template, owner=slice)
            net.save()
        else:
            net = nets[0]
            if net.subnet != n['subnet']:
                net.subnet = n['subnet']
                net.save()

        self.network_map[network_name] = net

    def create_networks(self, networks):
        for n in networks:
            self.create_epc_network(n)

    def create_networks_and_child_services(self, service_instance):
        self.obj = service_instance
        # Create service graph based on blueprint
        chosen_blueprint = service_instance.blueprint
        try:
            blueprint = next(
                b for b in blueprints if b['name'] == chosen_blueprint)
        except StopIteration:
            log.error('Chosen blueprint (%s) not found' % chosen_blueprint)

        self.create_networks(blueprint['networks'])

        service_instances = self.recursive_create_instances_and_links(blueprint['graph'], None, [])

        for si in service_instances:
            si.no_policy = False
            si.no_sync = False
            si.save()

    def handle_create(self, service_instance):
        self.handle_update(service_instance)

    def handle_update(self, service_instance):
        self.create_networks_and_child_services(service_instance)
