import os
import socket
import sys
import base64
import time
from django.db.models import F, Q
from xos.config import Config
from synchronizers.base.syncstep import SyncStep
from synchronizers.base.ansible_helper import run_template_ssh
from synchronizers.base.SyncInstanceUsingAnsible import SyncInstanceUsingAnsible
from core.models import Service, Slice, Tag
from services.vsg.models import VSGService, VCPE_KIND
from services.vtr.models import VTRService, VTRTenant
from services.volt.models import CordSubscriberRoot
from xos.logger import Logger, logging

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

logger = Logger(level=logging.INFO)

CORD_USE_VTN = getattr(Config(), "networking_use_vtn", False)

class SyncVTRTenant(SyncInstanceUsingAnsible):
    provides=[VTRTenant]
    observes=VTRTenant
    requested_interval=0
    template_name = "sync_vtrtenant.yaml"
    #service_key_name = "/opt/xos/services/vtr/vcpe_private_key"

    def __init__(self, *args, **kwargs):
        super(SyncVTRTenant, self).__init__(*args, **kwargs)

    def get_vtr_service(self, o):
        if not o.provider_service:
            return None

        vtrs = VTRService.objects.filter(id=o.provider_service.id)
        if not vtrs:
            return None

        return vtrs[0]

    def get_target(self, o):
        target = o.target
        if target:
            # CordSubscriberRoot is a Proxy object, and o.target will point to
            # the base class... so fix it up.
            if target.__class__.__name__ == "TenantRoot":
                target = CordSubscriberRoot.objects.get(id=target.id)
            return target
        return None

    def get_vcpe_service(self, o):
        target = self.get_target(o)
        if target and target.volt and target.volt.vcpe:
            vcpes = VSGService.get_service_objects().filter(id=target.volt.vcpe.provider_service.id)
            if not vcpes:
                return None
            return vcpes[0]
        return None

    def get_instance(self, o):
        target = self.get_target(o)
        if target and target.volt and target.volt.vcpe:
            return target.volt.vcpe.instance
        else:
            return None

    def get_key_name(self, instance):
        if instance.slice.service and (instance.slice.service.kind==VCPE_KIND):
            # We need to use the vsg service's private key. Onboarding won't
            # by default give us another service's private key, so let's assume
            # onboarding has been configured to add vsg_rsa to the vtr service.
            return "/opt/xos/services/vtr/keys/vsg_rsa"
        else:
            raise Exception("VTR doesn't know how to get the private key for this instance")

    def get_extra_attributes(self, o):
        vtr_service = self.get_vtr_service(o)
        vcpe_service = self.get_vcpe_service(o)

        if not vcpe_service:
            raise Exception("No vcpeservice")

        instance = self.get_instance(o)

        if not instance:
            raise Exception("No instance")

        target = self.get_target(o)

        s_tags = []
        c_tags = []
        if target and target.volt:
            s_tags.append(target.volt.s_tag)
            c_tags.append(target.volt.c_tag)

        fields = {"s_tags": s_tags,
                "c_tags": c_tags,
                "isolation": instance.isolation,
                "container_name": "vcpe-%s-%s" % (s_tags[0], c_tags[0]),
                "dns_servers": [x.strip() for x in vcpe_service.dns_servers.split(",")],

                "result_fn": "%s-vcpe-%s-%s" % (o.test, s_tags[0], c_tags[0]),
                "resultcode_fn": "code-%s-vcpe-%s-%s" % (o.test, s_tags[0], c_tags[0]) }

        # add in the sync_attributes that come from the vSG object
        # this will be wan_ip, wan_mac, wan_container_ip, wan_container_mac, ...
        if target and target.volt and target.volt.vcpe:
            for attribute_name in target.volt.vcpe.sync_attributes:
                fields[attribute_name] = getattr(target.volt.vcpe, attribute_name)

        # add in the sync_attributes that come from the SubscriberRoot object
        if target and hasattr(target, "sync_attributes"):
            for attribute_name in target.sync_attributes:
                fields[attribute_name] = getattr(target, attribute_name)

        for attribute_name in o.sync_attributes:
            fields[attribute_name] = getattr(o,attribute_name)

        return fields

    def sync_fields(self, o, fields):
        # the super causes the playbook to be run

        super(SyncVTRTenant, self).sync_fields(o, fields)

    def run_playbook(self, o, fields):
        o.result = ""

        result_fn = os.path.join("/opt/xos/synchronizers/vtr/result", fields["result_fn"])
        if os.path.exists(result_fn):
            os.remove(result_fn)

        resultcode_fn = os.path.join("/opt/xos/synchronizers/vtr/result", fields["resultcode_fn"])
        if os.path.exists(resultcode_fn):
            os.remove(resultcode_fn)

        super(SyncVTRTenant, self).run_playbook(o, fields)

        if os.path.exists(result_fn):
            o.result = open(result_fn).read()

        if os.path.exists(resultcode_fn):
            o.result_code = open(resultcode_fn).read()


    def delete_record(self, m):
        pass
