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

import json 
import yaml 
import copy

from app_home.cavaliba import TRUE_LIST
import app_home.cache as cache


from .field import Field

from app_data.models import DataClass
from app_data.models import DataInstance


widget_map = {
        "red_circle":    "&#x1f534;",
        "orange_circle": "&#x1F7E0;",
        "yellow_circle": "&#x1F7E1;",
        "green_circle":  "&#x1F7E2;",
        "purple_circle": "&#x1F7E3;",
        "brown_circle":  "&#x1F7E4;",
        "blue_circle":   "&#x1F535;",
        "white_circle":  "&#x25EF;",
        #"black_circle":  "&#11044;",
        #"black_circle":  "&#x25CF;",
        "black_circle":  "&#x2B24;",      # large
        "default" : ""
    }



def get_enumerate(enumname):

    ''' return list of values for enumerate Instance enumname'''
    global widget_map

    # cache
    cachekey = f"{enumname}"
    data = cache.cache2_enumerate.get(cachekey)
    if data:
        return data

    cache.cache2_enumerate.delete(cachekey)
    enumobj = DataInstance.objects.filter(classname="_enumerate", keyname=enumname, is_enabled=True).first()
    if not enumobj:
        return

    jsondata = json.loads(enumobj.data_json) 
    rawcontent = jsondata["content"]
    content = yaml.safe_load(rawcontent[0])


    # - classname: _enumerate
    #   keyname: enum_os
    #   is_enabled: True
    #   displayname: "OS Values"
    #   description: "Enumeration of OS"
    #   content: |
    #     - value: "Debian 10"
    #       long: string Debian 10
    #       num: int 1
    #       family: string Linux
    #       widget: green_circle
    #       price: float 9.50
    #       supported: boolean yes
    #     - value: "Win XP"
    #       long: string Windows XP
    #       num: int 2
    #       family: string Windows
    #       widget: red_circle
    #       price: float 99.95
    #       supported: boolean no

   
    # convert Widget to HTML string
    data2 = []
    for entry in content:
        # if 'widget' not in entry:
        #     continue
        w = entry.get("widget","default")
        if w.startswith("html"):
            w2 = w[5:]
        else:
            w2 = widget_map.get(w, entry.get("value","") )
        entry["widget"] = w2
        data2.append(entry)

    cache.cache2_enumerate.set(cachekey, data2)
    return data2
    

   


class FieldEnumerate(Field):
       

    def get_datapoint_ui_detail(self):

        datapoint = super().get_datapoint_ui_detail()

        enumerate_class = self.dataformat_ext
        enum_values = get_enumerate(enumerate_class)

# enum_values [{'value': 'OK', 'widget': '&#x1F7E2;'}, {'value': 'Info', 'widget': '&#x1F535;'}, {'value': 'Minor', 'widget': '&#x1F7E1;'}, {'value': 'Major', 'widget': '&#x1f534;'}, {'value': 'Critical', 'widget': '&#x2B24;'}, {'value': 'Other', 'widget': '&#1F7E4;'}, {'value': 'N/A', 'widget': '&#x25EF;'}]

#  [{'value': 'match ALL', 'widget': ''}, {'value': 'match ANY', 'widget': ''}]

        if not enum_values:
            return datapoint

        datapoint["value"] = []
        for entry in enum_values:
            if entry["value"] in self.value:
                datapoint["value"].append(entry)

        return datapoint   



    def get_datapoint_ui_edit(self):

        datapoint = super().get_datapoint_ui_edit()

        enumerate_class = self.dataformat_ext
        enum_values = get_enumerate(enumerate_class)

# [{'value': 'OK', 'widget': '&#x1F7E2;', 'zzzz': 'zzz3'}, {'value': 'Info', 'widget': '&#x1F535;'}, {'value': 'Minor', 'widget': '&#x1F7E1;'}, {'value': 'Major', 'widget': '&#x1f534;'}, {'value': 'Critical', 'widget': '&#x2B24;'}, {'value': 'Other', 'widget': '&#1F7E4;'}, {'value': 'N/A', 'widget': '&#x25EF;'}]

# [{'value': 'match ALL', 'widget': ''}, {'value': 'match ANY', 'widget': ''}]
        datapoint["value"] = []

        if not enum_values:
            return datapoint

        for i in enum_values:

            if "is_enabled" in i:
                if not i["is_enabled"]:
                    continue
            if i["value"] in self.value:
                i["selected"] = True
            else:
                i["selected"] = False


            datapoint["value"].append(i)

        return datapoint        




    def get_datapoint_for_export(self):

        if not self.is_multi():
            try:
                return self.value[0]
            except:
                # empty
                return ''
        return self.value



    def get_subfields(self):

        enumerate_name = self.dataformat_ext
        values = get_enumerate(enumerate_name)

        if not values:
            return {}

        if self.is_multi():
            return {}

#ok
        reply = {}
        for entry in values:
            if entry["value"] in self.value:
                for subkey, subval in entry.items():

                    if subkey == "value":
                        continue
                    v = subval
                    t = ""

                    if type(subval) is str:

                        if subval.startswith("string"):
                            v = subval[7:]
                            t = "string"

                        elif subval.startswith("int"):
                            try:
                                v = int(subval[4:])
                                t = "int"
                            except:
                                v = None
                        elif subval.startswith("float"):
                            try:
                                v = float(subval[6:])
                                t = "float"
                            except:
                                v = None
                        
                        elif subval.startswith("boolean"):
                            try:
                                v = subval[8:] in TRUE_LIST
                                t = "boolean"
                            except:
                                v = False

                        elif subval.startswith("date"):
                            v = subval[5:]
                            t = "date"

                        else:
                            v = subval
                            t = "string"
                    
                    reply[subkey]=[t,v]



        #   content: |
        #     - value: "Debian 10"
        #       long: string Debian 10
        #       num: int 1
        #       family: string Linux
        #       widget: green_circle
        #       price: float 9.50
        #       supported: boolean yes
        #     - value: "Win XP"
        #       long: string Windows XP
        #       num: int 2
        #       family: string Windows
        #       widget: red_circle
        #       price: float 99.95
        #       supported: boolean no    

        return reply


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