import os
import pdb
import json
import subprocess

from core.models import User

class XOSResource(object):
    xos_base_class = "XOSResource"
    xos_model = None
    name_field = "name"
    copyin_props = []
    provides = None

    def __init__(self, user, nodetemplate, engine):
        self.dirty = False
        self.deferred_sync = []
        self.user = user
        self.nodetemplate = nodetemplate
        self.engine = engine

    @property
    def full_name(self):
        return self.nodetemplate.name

    @property
    def obj_name(self):
        if "#" in self.nodetemplate.name:
            return self.nodetemplate.name.split("#",1)[1]
        else:
            return self.nodetemplate.name

    def get_all_required_node_names(self):
        results = []
        for reqs in self.nodetemplate.requirements:
            for (k,v) in reqs.items():
                results.append(v["node"])
        return results

    def get_requirements(self, relationship_name, throw_exception=False):
        """ helper to search the list of requirements for a particular relationship
            type.
        """

        results = []
        for reqs in self.nodetemplate.requirements:
            for (k,v) in reqs.items():
                if (v["relationship"] == relationship_name):
                    results.append(v["node"])

        if (not results) and throw_exception:
            raise Exception("Failed to find requirement in %s using relationship %s" % (self.full_name, relationship_name))

        return results

    def get_requirement(self, relationship_name, throw_exception=False):
        reqs = self.get_requirements(relationship_name, throw_exception)
        if not reqs:
            return None
        return reqs[0]

    def get_scalable(self):
        scalable = self.nodetemplate.get_capabilities().get("scalable", None)
        if scalable:
            return {"min_instances": scalable.get_property_value("min_instances"),
                    "max_instances": scalable.get_property_value("max_instances"),
                    "default_instances": scalable.get_property_value("default_instances")}
        else:
            return {}

    def get_property(self, name):
        return self.nodetemplate.get_property_value(name)

    def get_property_default(self, name, default=None):
        props = self.nodetemplate.get_properties()
        if props and name in props.keys():
            return props[name].value
        return default

    def get_xos_object(self, cls, throw_exception=True, **kwargs):
        # do the same parsing that we do for objname
        for (k,v) in kwargs.items():
            if (k=="name") and ("#" in v):
                kwargs[k] = v.split("#",1)[1]

        objs = cls.objects.filter(**kwargs)
        if not objs:
            if throw_exception:
                raise Exception("Failed to find %s filtered by %s" % (cls.__name__, str(kwargs)))
            return None
        return objs[0]

    def get_existing_objs(self):
        return self.xos_model.objects.filter(**{self.name_field: self.obj_name})

    def get_model_class_name(self):
        return self.xos_model.__name__

    def create_or_update(self):
        existing_objs = self.get_existing_objs()
        if existing_objs:
            if self.get_property_default("no-update", False):
                self.info("%s:%s (%s) already exists. Skipping update due to 'no-update' property" % (self.get_model_class_name(), self.obj_name, self.full_name))
            else:
                self.info("%s:%s (%s) already exists" % (self.get_model_class_name(), self.obj_name, self.full_name))
                self.update(existing_objs[0])
        else:
            if self.get_property_default("no-create", False):
                self.info("%s:%s (%s) does not exist, but 'no-create' is specified" % (self.get_model_class_name(), self.obj_name, self.full_name))
            else:
                self.create()

    def can_delete(self, obj):
        if self.get_property_default("no-delete",False):
            self.info("%s:%s %s is marked 'no-delete'. Skipping delete." % (self.get_model_class_name(), self.obj_name, self.full_name))
            return False
        return True

    def postprocess_privileges(self, roleclass, privclass, rolemap, obj, toFieldName):
        for (rel, role) in rolemap:
            for email in self.get_requirements(rel):
                role_obj = self.get_xos_object(roleclass, throw_exception=False, role=role)
                if not role_obj:
                    # if the role doesn't exist, make it
                    self.info("Creating %s %s" % (roleclass.__name__, role))
                    role_obj = roleclass(role=role)
                    role_obj.save()

                user = self.get_xos_object(User, email=email)
                if not privclass.objects.filter(user=user, role=role_obj, **{toFieldName: obj}):
                    sp = privclass(user=user, role=role_obj, **{toFieldName: obj})
                    sp.save()
                    self.info("Added privilege on %s role %s for %s" % (str(obj), str(role), str(user)))

    def postprocess(self, obj):
        pass

    def intrinsic_get_artifact(self, obj=None, name=None, method=None):
        if obj!="SELF":
            raise Exception("only SELF is supported for get_artifact first arg")
        if method!="LOCAL_FILE":
            raise Exception("only LOCAL_FILE is supported for get_artifact third arg")

        for (k,v) in self.nodetemplate.entity_tpl.get("artifacts", {}).items():
            if k == name:
                if not os.path.exists(v):
                    raise Exception("Artifact local file %s for artifact %s does not exist" % (v, k))
                return open(v).read()

        raise Exception("artifact %s not found" % name)

    def intrinsic_get_script_env(self, obj=None, name=None, varname=None, method=None):
        if obj!="SELF":
            raise Exception("only SELF is supported for get_artifact first arg")
        if method!="LOCAL_FILE":
            raise Exception("only LOCAL_FILE is supported for get_artifact fourth arg")

        for (k,v) in self.nodetemplate.entity_tpl.get("artifacts", {}).items():
            if k == name:
                if not os.path.exists(v):
                    raise Exception("Artifact local file %s for artifact %s does not exist" % (v, k))
                return subprocess.Popen('/bin/bash -c "source %s &> /dev/null; echo \\$%s"' % (v, varname), shell=True, stdout=subprocess.PIPE).stdout.read().strip()

        raise Exception("artifact %s not found" % name)

    def try_intrinsic_function(self, v):
        try:
            jsv = v.replace("'", '"')
            jsv = json.loads(jsv)
        except:
            #import traceback
            #traceback.print_exc()
            return v

        if type(jsv)!=dict:
            return v

        if "get_artifact" in jsv:
            return self.intrinsic_get_artifact(*jsv["get_artifact"])
        elif "get_script_env" in jsv:
            return self.intrinsic_get_script_env(*jsv["get_script_env"])

        return v

    def get_xos_args(self):
        args = {}

        if self.name_field:
            args[self.name_field] = self.obj_name

        # copy simple string properties from the template into the arguments
        for prop in self.copyin_props:
            v = self.get_property(prop)

            v = self.try_intrinsic_function(v)

            if v is not None:
                args[prop] = v

        return args

    def create(self):
        xos_args = self.get_xos_args()
        xos_obj = self.xos_model(**xos_args)
        if self.user:
            xos_obj.caller = self.user
        xos_obj.save()

        self.info("Created %s '%s'" % (self.xos_model.__name__,str(xos_obj)))

        self.postprocess(xos_obj)

    def update(self, obj):
        xos_args = self.get_xos_args()
        for (k,v) in xos_args.items():
            setattr(obj, k, v)
        self.postprocess(obj)
        obj.save()

    def delete(self, obj):
        if (self.can_delete(obj)):
            self.info("destroying object %s" % str(obj))
            obj.delete(purge=True)   # XXX TODO: turn off purge before production

    def info(self, s):
        self.engine.log(s)

