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


from .field import Field

from app_data.models import DataInstance
from app_data.schema import Schema 


import app_home.cache as cache


# 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:
            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:
            return []


    def get_first_value(self):
        ''' name of first target instance'''
        try:
            return self.value[0]
        except:
            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")
                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"] }
                    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")
            for i in instances:
                item = { "key":i["keyname"], "display":i["displayname"], "id":i["id"] }
                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}
                datapoint["value"].append(item)
            # selected = False
            # item = { "key":"test03232", "selected":selected}
            # 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:
                if i.keyname in self.value:
                    selected = True
                    # item = { "key":i.keyname, "selected":selected}
                    # datapoint["value"].append( item )
                else:
                    selected = False
                item = {"key": i.keyname, "display": i.displayname, "selected": selected}
                datapoint["value"].append(item)

        return datapoint


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