import os
import pdb
import sys
import tempfile
sys.path.append("/opt/tosca")
from translator.toscalib.tosca_template import ToscaTemplate

from core.models import Slice,Instance,User,Flavor,Node,Image
from nodeselect import XOSNodeSelector
from imageselect import XOSImageSelector
from flavorselect import XOSFlavorSelector

from xosresource import XOSResource

class XOSCompute(XOSResource):
    provides = ["tosca.nodes.Compute", "tosca.nodes.Compute.Container"]
    xos_model = Instance

    def select_compute_node(self, user, v, hostname=None):
        mem_size = v.get_property_value("mem_size")
        num_cpus = v.get_property_value("num_cpus")
        disk_size = v.get_property_value("disk_size")

        flavor = XOSFlavorSelector(user, mem_size=mem_size, num_cpus=num_cpus, disk_size=disk_size).get_flavor()

        compute_node = XOSNodeSelector(user, mem_size=mem_size, num_cpus=num_cpus, disk_size=disk_size, hostname=hostname).get_nodes(1)[0]

        return (compute_node, flavor)

    def select_image(self, user, v):
        distribution = v.get_property_value("distribution")
        version = v.get_property_value("version")
        type = v.get_property_value("type")
        architecture = v.get_property_value("architecture")

        return XOSImageSelector(user, distribution=distribution, version=version, type=type, architecture=architecture).get_image()

    def get_xos_args(self, name=None, index=None):
        nodetemplate = self.nodetemplate

        if not name:
            name = nodetemplate.name

        args = {"name": name}

        host=None
        flavor=None
        image=None

        sliceName = self.get_requirement("tosca.relationships.MemberOfSlice", throw_exception=True)
        slice = self.get_xos_object(Slice, name=sliceName)

        # locate it one the same host as some other instance
        colocate_host = None
        colocate_instance_name = self.get_requirement("tosca.relationships.SameHost")
        if index is not None:
            colocate_instance_name = "%s-%d" % (colocate_instance_name, index)
        colocate_instances = Instance.objects.filter(name=colocate_instance_name)
        if colocate_instances:
            colocate_host = colocate_instances[0].node.name
            self.info("colocating on %s" % colocate_host)

        imageName = self.get_requirement("tosca.relationships.UsesImage", throw_exception=False)
        image = self.get_xos_object(Image, name=imageName)

        capabilities = nodetemplate.get_capabilities()
        for (k,v) in capabilities.items():
            if (k=="host") and (not host):
                (compute_node, flavor) = self.select_compute_node(self.user, v, hostname=colocate_host)
            elif (k=="os") and (not image):
                image = self.select_image(self.user, v)

        if not compute_node:
            raise Exception("Failed to pick a host")
        if not image:
            raise Exception("Failed to pick an image")
        if not flavor:
            raise Exception("Failed to pick a flavor")

        args["image"] = image
        args["slice"] = slice
        args["flavor"] = flavor
        args["node"] = compute_node
        args["deployment"] = compute_node.site_deployment.deployment

        if nodetemplate.type == "tosca.nodes.Compute.Container":
            args["isolation"] = "container"

        return args

    def create(self, name = None, index = None):
        xos_args = self.get_xos_args(name=name, index=index)
        instance = Instance(**xos_args)
        instance.caller = self.user
        instance.no_sync = True
        instance.save()
        self.deferred_sync.append(instance)

        self.info("Created Instance '%s' on node '%s' using flavor '%s' and image '%s'" %
                  (str(instance), str(instance.node), str(instance.flavor), str(instance.image)))

    def create_or_update(self):
        scalable = self.get_scalable()
        if scalable:
            default_instances = scalable.get("default_instances",1)
            for i in range(0, default_instances):
                name = "%s-%d" % (self.nodetemplate.name, i)
                existing_instances = Instance.objects.filter(name=name)
                if existing_instances:
                    self.info("%s %s already exists" % (self.xos_model.__name__, name))
                    self.update(existing_instances[0])
                else:
                    self.create(name, index=i)
        else:
            super(XOSCompute,self).create_or_update()

    def get_existing_objs(self):
        scalable = self.get_scalable()
        if scalable:
            existing_instances = []
            max_instances = scalable.get("max_instances",1)
            for i in range(0, max_instances):
                name = "%s-%d" % (self.nodetemplate.name, i)
                existing_instances = existing_instances + list(Instance.objects.filter(name=name))
            return existing_instances
        else:
            return super(XOSCompute,self).get_existing_objs()


