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

"""
FieldInt: dataformat "int". dataformat_ext may carry "gte_/gt_/lte_/lt_<num>"
range constraints, checked in is_valid().

Method inventory: __init__, get_datapoint_ui_detail, get_datapoint_ui_edit,
merge_request, merge_import, is_valid.
"""

from .field import Field


# -------------
# INT
# -------------
class FieldInt(Field):
    def __init__(self, fieldname, fieldschema, alljson):
        """Like Field.__init__, but unpacks a space-separated default_value string
        into a list of ints (only used when alljson has no value for this field)."""
        super().__init__(fieldname, fieldschema, alljson)

        # if no json, unpack default_value
        if not alljson:
            if self.default_value:
                ml = self.default_value.split()
                try:
                    self.value = [int(i) for i in ml]
                except Exception:
                    self.value = []

    def get_datapoint_ui_detail(self):
        """Detail datapoint with value = values joined by a space."""
        datapoint = super().get_datapoint_ui_detail()
        a = [str(i) for i in self.value]
        datapoint["value"] = " ".join(a)
        return datapoint

    def get_datapoint_ui_edit(self):
        """Edit datapoint with value = values joined by a space."""
        datapoint = super().get_datapoint_ui_edit()
        # force to string
        a = [str(i) for i in self.value]
        datapoint["value"] = " ".join(a)
        return datapoint

    def merge_request(self, request):
        """data is a list of string ["3 5", ...] from request.POST.getlist"""

        data = request.POST.getlist(self.fieldname, default=[])
        self.value = []
        try:
            values = data[0].split()
        except Exception:
            return
        for i in values:
            try:
                self.value.append(int(i))
            except Exception:
                pass

    def merge_import(self, data):
        """
        source: csv/json/yaml, mono or multi value
        data=[a,b,c, ...] / data=a
        a="3" / a="20 32" / a=3
        no thousand white separator allowed (strop in pipeline)
        """
        self.value = []
        if type(data) is int:
            self.value.append(data)
        elif type(data) is str:
            xi = data.split()
            for i in xi:
                try:
                    self.value.append(int(i))
                except Exception:
                    pass
        elif type(data) is list:
            for x in data:
                if type(x) is int:
                    self.value.append(x)
                elif type(x) is str:
                    xi = data.split()
                    for i in xi:
                        try:
                            self.value.append(int(i))
                        except Exception:
                            pass
        if not self.is_multi():
            if len(self.value) > 1:
                self.value = [self.value[0]]

    def is_valid(self):
        """Cardinality check (super) plus: each value must parse as int and satisfy any
        gte_/gt_/lte_/lt_ range constraint from dataformat_ext."""
        r = super().is_valid()
        for v in self.value:
            if type(v) is str:
                if len(v) == 0:
                    continue
            try:
                int(str(v))
            except Exception:
                return False

            options = self.dataformat_ext
            if options:
                dictopt = options.split()

                for opt in dictopt:
                    # greater or equal
                    if opt.startswith("gte_"):
                        (tmp, valopt) = opt.split("_")
                        for v in self.value:
                            try:
                                if v < int(valopt):
                                    return False
                            except Exception:
                                pass

                    # greater strict
                    if opt.startswith("gte_"):
                        (tmp, valopt) = opt.split("_")
                        for v in self.value:
                            try:
                                if v <= int(valopt):
                                    return False
                            except Exception:
                                pass

                    # lesser or equal
                    if opt.startswith("lte_"):
                        (tmp, valopt) = opt.split("_")
                        for v in self.value:
                            try:
                                if v > int(valopt):
                                    return False
                            except Exception:
                                pass

                    # lesser strict
                    if opt.startswith("lt_"):
                        (tmp, valopt) = opt.split("_")
                        for v in self.value:
                            try:
                                if v >= int(valopt):
                                    return False
                            except Exception:
                                pass

        return r
