import os
import requests
import socket
import sys
import base64
from django.db.models import F, Q
from xos.config import Config
from observer.syncstep import SyncStep
from observer.ansible import run_template_ssh
from core.models import Service
from services.cord.models import VCPEService, VCPETenant, VBNGTenant, VBNGService
from hpc.models import HpcService, CDNPrefix
from util.logger import Logger, logging

# VBNG_API = "http://10.0.3.136:8181/onos/virtualbng/privateip/"

# hpclibrary will be in steps/..
parentdir = os.path.join(os.path.dirname(__file__),"..")
sys.path.insert(0,parentdir)

logger = Logger(level=logging.INFO)

class SyncVBNGTenant(SyncStep):
    provides=[VCPETenant]
    observes=VCPETenant
    requested_interval=0

    def __init__(self, **args):
        SyncStep.__init__(self, **args)

    def fetch_pending(self, deleted):
        if (not deleted):
            objs = VBNGTenant.get_tenant_objects().filter(Q(enacted__lt=F('updated')) | Q(enacted=None),Q(lazy_blocked=False))
        else:
            objs = VBNGTenant.get_deleted_tenant_objects()

        return objs

    def defer_sync(self, o, reason):
        logger.info("defer object %s due to %s" % (str(o), reason))
        raise Exception("defer object %s due to %s" % (str(o), reason))

    def get_vbng_service(self, o):
        if not o.provider_service:
             raise Exception("vBNG tenant %s has no provider_service" % str(o.id))
        services = VBNGService.get_service_objects().filter(id = o.provider_service.id)
        if not services:
             raise Exception("vBNG tenant %s is associated with the wrong kind of provider_service" % str(o.id))
        return services[0]

    def get_vbng_url(self, o):
        service = self.get_vbng_service(o)

        # if the service object specifies a vbng_url, then use it
        if service.vbng_url:
            return service.vbng_url

        # otherwise, see if the service has tenancy in ONOS
        for tenant in service.subscribed_tenants.all():
            if tenant.provider_service and tenant.provider_service.kind == "onos":
                onos_service = tenant.provider_service
                if not onos_service.slices.exists():
                    raise Exception("vBNG service is linked to an ONOSApp, but the App's Service has no slices")
                onos_slice = onos_service.slices.all()[0]
                if not onos_slice.instances.exists():
                    raise Exception("vBNG service is linked to an ONOSApp, but the App's Service's Slice has no instances")
                instance = onos_slice.instances.all()[0]

                #onos_app = ONOSApp.objects.filter(id = tenant.id)
                #instance = onos_app.instance
                #if not instance:
                #    raise Exception("ONOSApp has no instance")

                if not instance.instance_name:
                    raise Exception("vBNG service is linked to an ONOSApp, but the App's Service's Slice's first instance is not instantiated")
                ip = instance.get_network_ip("nat")
                if not ip:
                    raise Exception("vBNG service is linked to an ONOSApp, but the App's Service's Slice's first instance does not have an ip")

                logger.info("Using ip %s from ONOS Instance %s" % (ip, instance))

                return "http://%s:8181/onos/virtualbng/" % ip

        raise Exception("vBNG service does not have vbng_url set, and is not linked to an ONOSApp")

    def get_private_interface(self, o):
        vcpes = VCPETenant.get_tenant_objects().all()
        vcpes = [x for x in vcpes if (x.vbng is not None) and (x.vbng.id == o.id)]
        if not vcpes:
            raise Exception("No vCPE tenant is associated with vBNG %s" % str(o.id))
        if len(vcpes)>1:
            raise Exception("More than one vCPE tenant is associated with vBNG %s" % str(o.id))

        vcpe = vcpes[0]
        instance = vcpe.instance

        if not instance:
            raise Exception("No instance associated with vBNG %s" % str(o.id))

        if not vcpe.wan_ip:
            self.defer_sync(o, "does not have a WAN IP yet")

        if not vcpe.wan_container_mac:
            # this should never happen; container MAC is computed from WAN IP
            self.defer_sync(o, "does not have a WAN container MAC yet")

        return (vcpe.wan_ip, vcpe.wan_container_mac, vcpe.instance.node.name)

    def sync_record(self, o):
        logger.info("sync'ing VBNGTenant %s" % str(o))

        if not o.routeable_subnet:
            (private_ip, private_mac, private_hostname) = self.get_private_interface(o)
            logger.info("contacting vBNG service to request mapping for private ip %s mac %s host %s" % (private_ip, private_mac, private_hostname) )

            url = self.get_vbng_url(o) + "privateip/%s/%s/%s" % (private_ip, private_mac, private_hostname)
            logger.info( "vbng url: %s" % url )
            r = requests.post(url )
            if (r.status_code != 200):
                raise Exception("Received error from bng service (%d)" % r.status_code)
            logger.info("received public IP %s from private IP %s" % (r.text, private_ip))

            if r.text == "0":
                raise Exception("VBNG service failed to return a routeable_subnet (probably ran out)")

            o.routeable_subnet = r.text
            o.mapped_ip = private_ip
            o.mapped_mac = private_mac
            o.mapped_hostname = private_hostname

        o.save()

    def delete_record(self, o):
        logger.info("deleting VBNGTenant %s" % str(o))

        if o.mapped_ip:
            private_ip = o.mapped_ip
            logger.info("contacting vBNG service to delete private ip %s" % private_ip)
            r = requests.delete(self.get_vbng_url(o) + "privateip/%s" % private_ip, )
            if (r.status_code != 200):
                raise Exception("Received error from bng service (%d)" % r.status_code)

