#!/usr/bin/env python3
import random
from typing import Optional, cast

from typing_extensions import Self

from nicegui import ui
from nicegui.binding import BindableProperty, bind_from


class colorful_label(ui.label):
    """A label with a bindable background color."""

    # This class variable defines what happens when the background property changes.
    background = BindableProperty(
        on_change=lambda sender, value: cast(Self, sender)._handle_background_change(value))

    def __init__(self, text: str = '') -> None:
        super().__init__(text)
        self.background: Optional[str] = None  # initialize the background property

    def _handle_background_change(self, bg_class: str) -> None:
        """Update the classes of the label when the background property changes."""
        self._classes = [c for c in self._classes if not c.startswith('bg-')]
        self._classes.append(bg_class)


temperatures = {'Berlin': 5, 'New York': 15, 'Tokio': 25}
ui.button(icon='refresh', on_click=lambda: temperatures.update({city: random.randint(0, 30) for city in temperatures}))


for city in temperatures:
    label = colorful_label().classes('w-48 text-center') \
        .bind_text_from(temperatures, city, backward=lambda t, city=city: f'{city} ({t}°C)')
    # Bind background color from temperature.
    # There is also a bind_to method which would propagate changes from the label to the temperatures dictionary
    # and a bind method which would propagate changes both ways.
    bind_from(self_obj=label, self_name='background',
              other_obj=temperatures, other_name=city,
              backward=lambda t: 'bg-green' if t < 10 else 'bg-yellow' if t < 20 else 'bg-orange')

ui.run()
