from ..constants import BOTTOM, LEFT, RIGHT, TOP


class directional_property:
    ASSIGNMENT_SCHEMES = {
        #   T  R  B  L
        1: [0, 0, 0, 0],
        2: [0, 1, 0, 1],
        3: [0, 1, 2, 1],
        4: [0, 1, 2, 3],
    }

    def __init__(self, name_format):
        """Define a property that proxies for top/right/bottom/left alternatives.

        :param name_format: The format from which to generate subproperties. "{}" will
            be replaced with "_top", etc.
        """
        self.property_names = [
            name_format.format(f"_{direction}")
            for direction in [TOP, RIGHT, BOTTOM, LEFT]
        ]

    def __set_name__(self, style_class, name):
        self.name = name
        style_class._BASE_ALL_PROPERTIES[style_class].add(name)

    def __get__(self, style, style_class=None):
        if style is None:
            return self

        return tuple(style[name] for name in self.property_names)

    def __set__(self, style, value):
        if value is self:
            # This happens during autogenerated dataclass __init__ when no value is
            # supplied.
            return

        if not isinstance(value, tuple):
            value = (value,)

        if order := self.ASSIGNMENT_SCHEMES.get(len(value)):
            with style.batch_apply():
                for name, index in zip(self.property_names, order):
                    style[name] = value[index]
        else:
            raise ValueError(
                f"Invalid value for '{self.name}'; value must be a number, or a 1-4 "
                f"tuple."
            )

    def __delete__(self, style):
        with style.batch_apply():
            for name in self.property_names:
                del style[name]

    def is_set_on(self, style):
        return any(name in style for name in self.property_names)
