# (c) cavaliba.com - data - field - schema


import app_home.cache as cache
from app_data.models import DataInstance
from app_data.schema import Schema

from .field import Field

# def local_get_class_by_name(keyname):

#     # no-cache
#     #dataclass = DataClass.objects.filter(keyname=keyname).first()
#     #return dataclass

#     if not keyname in cache.cache_classname:
#         cache.cache_classname[keyname] = DataClass.objects.filter(keyname=keyname).first()
#     return cache.cache_classname[keyname]


def local_get_instances(classname=None, is_enabled=None):
    """class keyname => Queryset"""

    if is_enabled:
        instances = DataInstance.objects.filter(classname=classname, is_enabled=is_enabled)
    else:
        instances = DataInstance.objects.filter(classname=classname)
    return instances


def local_get_instances_from_keylist(classname=None, keylist=[], is_enabled=None):
    """class keyname => Queryset"""

    if is_enabled:
        instances = DataInstance.objects.filter(
            classname=classname, keyname__in=keylist, is_enabled=is_enabled
        )
    else:
        instances = DataInstance.objects.filter(classname=classname, keyname__in=keylist)
    return instances


def local_get_instance_by_name(keyname=None, classname=None):
    return DataInstance.objects.filter(classname=classname, keyname=keyname).first()


# -------------
#  SCHEMA
# -------------
class FieldSchema(Field):
    def get_classname(self):
        """dataformat_ext: classname inject1 inject2 ..."""
        try:
            return self.dataformat_ext.split()[0]
        except Exception:
            return ""

    def get_eav_format(self):
        # schema:classname
        c = self.get_classname()
        return f"schema:{c}"

    def get_subfields(self):
        """dataformat_ext: classname inject1 inject2 ..."""
        try:
            return self.dataformat_ext.split()[1:]
        except Exception:
            return []

    def get_first_value(self):
        """name of first target instance"""
        try:
            return self.value[0]
        except Exception:
            return

    def get_attribute(self):
        """returns list of DB obj"""

        reply = []
        classname = self.get_classname()

        for iname in self.value:
            instobj = local_get_instance_by_name(keyname=iname, classname=classname)
            reply.append(instobj)
        return reply

    def get_datapoint_ui_detail(self):
        """
        Returns list of datapoints [ {}, {}, ...]
        datapoint["value"] = [ { key:, display:, }  , ... ]
        """

        datapoint = super().get_datapoint_ui_detail()

        datapoint["value"] = []

        classname = self.get_classname()
        datapoint["schema"] = classname

        # use cache for single value
        if len(self.value) == 1:
            # NEXT : merge with cache.cache_instance_name from DATA get_instance_by_name
            # key = f"{classname}::{iname}"
            # if key not in cache.cache_instance_name:
            # obj = DataInstance.objects.filter(classname=classname, keyname=iname).first()
            # ckey = f"{classname}::{self.value[0]}"

            # if ckey in cache.cache_fieldschema_detail:
            #     dp = cache.cache_fieldschema_detail[ckey]
            #     datapoint["value"] = dp
            # else:
            #     instances = DataInstance.objects.filter(classname=classname, keyname__in=self.value).values("id","keyname","displayname")
            #     for i in instances:
            #         item = { "key":i["keyname"], "display":i["displayname"],  "id":i["id"] }
            #         datapoint["value"].append(item)
            #     cache.cache_fieldschema_detail[ckey] = datapoint["value"]

            cachekey = f"{classname}::{self.value[0]}"
            dp = cache.cache2_datapoint.get(cachekey)
            if dp:
                datapoint["value"] = dp
            else:
                instances = DataInstance.objects.filter(
                    classname=classname, keyname__in=self.value
                ).values("id", "keyname", "displayname", "is_enabled")
                for i in instances:
                    if i["displayname"] and len(i["displayname"]) > 0:
                        dn = i["displayname"]
                    else:
                        dn = i["keyname"]
                    item = {
                        "key": i["keyname"],
                        "display": dn,
                        "id": i["id"],
                        "is_enabled": i["is_enabled"],
                    }
                    datapoint["value"].append(item)
                cache.cache2_datapoint.set(cachekey, datapoint["value"])

        else:
            instances = DataInstance.objects.filter(
                classname=classname, keyname__in=self.value
            ).values("id", "keyname", "displayname", "is_enabled")
            for i in instances:
                item = {
                    "key": i["keyname"],
                    "display": i["displayname"],
                    "id": i["id"],
                    "is_enabled": i["is_enabled"],
                }
                datapoint["value"].append(item)

        # MISSING assets: if datapoint["value"] is still empty (no matching instance)
        # display a "??? keyname" datapoint
        if len(datapoint["value"]) == 0:
            for i in self.value:
                item = {"key": "", "display": f"?? - {i}", "id": 999999999999}
                datapoint["value"].append(item)

        return datapoint

    def get_datapoint_ui_edit(self):

        # value: [ { 'key':'keyname' , 'selected':True/False }, ...    ]

        datapoint = super().get_datapoint_ui_edit()

        datapoint["value"] = []

        classname = self.get_classname()
        schema = Schema.from_name(classname)

        datapoint["dataformat_ext"] = classname
        datapoint["bigset"] = schema.is_bigset

        # bigset : selected items only (ajax for the rest)
        if datapoint["bigset"]:
            limited_instances_obj = local_get_instances_from_keylist(
                classname=classname, keylist=self.value
            )
            for i in limited_instances_obj:
                selected = True
                item = {
                    "key": i.keyname,
                    "display": i.displayname,
                    "selected": selected,
                    "is_enabled": i.is_enabled,
                }
                datapoint["value"].append(item)

        # no bigset : all available and selected items
        else:
            all_instances_obj = local_get_instances(classname=classname)
            for i in all_instances_obj:
                selected = i.keyname in self.value
                item = {
                    "key": i.keyname,
                    "display": i.displayname,
                    "selected": selected,
                    "is_enabled": i.is_enabled,
                }
                datapoint["value"].append(item)

        return datapoint

    def is_valid(self):
        r = super().is_valid()
        # TODO
        return r
