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 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 fetch_pending(self, deleted):
        if (not deleted):
            objs = VTRTenant.get_tenant_objects().filter(Q(enacted__lt=F('updated')) | Q(enacted=None),Q(lazy_blocked=False))
        else:
            objs = VTRTenant.get_deleted_tenant_objects()

        return objs

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

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

        return vtrs[0]

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

    def get_instance(self, o):
        if o.target and o.target.volt and o.target.volt.vcpe:
            return o.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")

        s_tags = []
        c_tags = []
        if o.target and o.target.volt:
            s_tags.append(o.target.volt.s_tag)
            c_tags.append(o.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 o.target and o.target.volt and o.target.volt.vcpe:
            for attribute_name in o.target.volt.vcpe.sync_attributes:
                fields[attribute_name] = getattr(o.target.volt.vcpe, attribute_name)

        # add in the sync_attributes that come from the SubscriberRoot object
        if o.target and hasattr(o.target, "sync_attributes"):
            for attribute_name in o.target.sync_attributes:
                fields[attribute_name] = getattr(o.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
