from ursina import Entity, Text, camera, Button, color, mouse, Vec3
from math import floor


class ButtonList(Entity):
    def __init__(self, button_dict, button_height=1.1, width=.5, popup=False, color=Button.default_color, highlight_color=color.white33, selected_color=color.azure, font=Text.default_font, clear_selected_on_enable=True, **kwargs):
        self.clear_selected_on_enable = clear_selected_on_enable
        self.button_height = button_height
        self.width = width
        super().__init__(parent=camera.ui, position=(-(width/2), .45))

        self.text_entity = Text(parent=self, font=font, origin=(-.5,.5), text='empty', world_scale=20, z=-.1, x=.01, y=-(button_height*.25*Text.size), line_height=button_height)
        self.bg = Entity(parent=self, model='quad', origin=(-.5,.5), scale=width, color=color, collider='box')
        self.highlight = Entity(parent=self.bg, model='quad', color=highlight_color, scale=(1,self.button_height), origin=(-.5,.5), z=-.01, add_to_scene_entities=False)
        self.selection_marker = Entity(parent=self.bg, model='quad', color=selected_color, scale=(1,self.button_height), origin=(-.5,.5), z=-.02, enabled=False, add_to_scene_entities=False)
        self.button_dict = button_dict

        self.popup = popup
        if self.popup:
            self.close_button = Entity(parent=self, scale=Vec3(100,100,.1), model='quad', collider='box', visible_self=False, on_click=self.disable)

        for key, value in kwargs.items():
            setattr(self, key, value)


    @property
    def button_dict(self):
        return self._button_dict

    @button_dict.setter
    def button_dict(self, value):
        self._button_dict = value
        self.actions = list(self._button_dict.values())
        self.bg.scale_y = self.button_height * len(value) * Text.size
        # self.bg.model='circle'
        self.bg.model = 'quad'
        self.bg.origin = self.bg.origin

        self.text_entity.text = '\n'.join(self.button_dict.keys())
        self.text_entity.line_height = self.button_height
        if len(value) > 0:
            self.highlight.scale_y = 1 / len(value)
            self.selection_marker.scale_y = 1 / len(value)


    def input(self, key):
        # handle click here instead of in on_click so you can assign a custom on_click function
        if key == 'left mouse down' and self.bg.hovered:
            y = floor(-mouse.point.y * len(self.button_dict))
            y = min(y, len(self.button_dict)-1)

            action = self.actions[y]
            self.selection_marker.enabled = True
            self.selection_marker.y = self.highlight.y

            if callable(action):
                action()

            if self.popup:
                self.disable()

        if key == 'left mouse down' and not self.bg.hovered:
            self.selection_marker.enabled = False


    def update(self):
        self.highlight.enabled = mouse.hovered_entity == self.bg
        if mouse.hovered_entity == self.bg:
            y = floor(-mouse.point.y * len(self.button_dict))
            y = min(y, len(self.button_dict)-1)
            self.highlight.y = -y / len(self.button_dict)


    def on_disable(self):
        self.selection_marker.enabled = False

    def on_enable(self):
        if self.clear_selected_on_enable:
            self.selected = None


    @property
    def selected(self):
        return getattr(self, '_selected', None)
    @selected.setter
    def selected(self, value):
        self._selected = value
        if not hasattr(self, 'selection_marker'):
            return

        if not value:
            self.selection_marker.enabled = False
            return

        self.selection_marker.enabled = True
        y = list(self.button_dict.keys()).index(value)
        self.selection_marker.y = -y / len(self.button_dict)


if __name__ == '__main__':
    from ursina import Ursina, Func
    app = Ursina()

    default = Func(print, 'not yet implemented')

    def test(a=1, b=2):
        print('------:', a, b)

    button_dict = {}
    for i in range(6, 20):
        button_dict[f'button {i}'] = Func(print, i)

    bl = ButtonList(button_dict, font=Text.default_monospace_font, button_height=1.5, popup=0, clear_selected_on_enable=False)
    def input(key):
        if key == 'space':
            bl.button_dict = {
                'one' :     None,
                'two' :     default,
                'tree' :    Func(test, 3, 4),
                'four' :    Func(test, b=3, a=4),
            }
        if key == 'o':
            bl.enabled = True

    bl.selected = 'button 7'

    bl.button_dict = {}

    app.run()
