"""Demo of ubo-menu widget."""
from __future__ import annotations

import datetime
import os
from functools import cached_property
from threading import Thread
from typing import TYPE_CHECKING, Literal

from headless_kivy_pi import setup_headless
from kivy.app import Widget
from kivy.base import Clock
from kivy.metrics import dp
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.label import Label

from ubo_gui.gauge import GaugeWidget
from ubo_gui.volume import VolumeWidget

os.environ["KIVY_METRICS_DENSITY"] = "1"
os.environ["KIVY_NO_CONFIG"] = "1"
os.environ["KIVY_NO_FILELOG"] = "1"

setup_headless()

from kivy.core.window import (  # noqa: E402
    Keyboard,
    Window,
    WindowBase,
)

from ubo_gui.app import UboApp  # noqa: E402
from ubo_gui.menu import MenuWidget  # noqa: E402
from ubo_gui.menu.constants import SHORT_WIDTH  # noqa: E402
from ubo_gui.notification import (  # noqa: E402
    Importance,
    notification_manager,
)
from ubo_gui.prompt import PromptWidget  # noqa: E402

if TYPE_CHECKING:
    from menu import Menu

    Modifier = Literal["ctrl", "alt", "meta", "shift"]

notification_manager.notify(
    title="Low priority",
    content="Something happened but it is not important and this content is very long "
    "since we need a very long content to check the scrollability of the widget",
    importance=Importance.LOW,
    sender="demo",
)
notification_manager.notify(
    title="Medium priority",
    content="Something happened and it is somehow important",
    importance=Importance.MEDIUM,
    sender="demo",
)
notification_manager.notify(
    title="High priority",
    content="Something happened and it is important",
    importance=Importance.HIGH,
    sender="demo",
)
notification_manager.notify(
    title="Critical priority",
    content="Something happened and it is critically important",
    importance=Importance.CRITICAL,
    sender="demo",
)


class WifiPrompt(PromptWidget):
    icon = "wifi_off"
    prompt = "Not Connected"
    first_option_label = "Add"
    first_option_icon = "add"

    def first_option_callback(self: WifiPrompt):
        notification_manager.notify(
            title="Wifi added",
            content="This Wifi network has been added",
            icon="wifi",
            sender="Wifi",
        )

    second_option_label = "Forget"
    second_option_icon = "delete"

    def second_option_callback(self: WifiPrompt):
        notification_manager.notify(
            title="Wifi forgotten",
            content="This Wifi network is forgotten",
            importance=Importance.CRITICAL,
            sender="Wifi",
        )


SETTINGS_MENU: Menu = {
    "title": "Settings",
    "heading": "Please choose",
    "sub_heading": "This is sub heading",
    "items": [
        {
            "label": "WiFi",
            "application": WifiPrompt,
            "icon": "wifi",
        },
        {
            "label": "Bluetooth",
            "action": lambda: print("Bluetooth"),
            "icon": "bluetooth",
        },
        {
            "label": "Audio",
            "action": lambda: print("Audio"),
            "icon": "volume_up",
        },
    ],
}

MAIN_MENU: Menu = {
    "title": "Main",
    "heading": "What are you going to do?",
    "sub_heading": "Choose from the options",
    "items": [
        {
            "label": "Settings",
            "icon": "settings",
            "sub_menu": SETTINGS_MENU,
        },
        {
            "label": "Apps",
            "action": lambda: print("Apps"),
            "icon": "apps",
        },
        {
            "label": "About",
            "action": lambda: print("About"),
            "icon": "info",
        },
    ],
}


HOME_MENU: Menu = {
    "title": "Dashboard",
    "items": [
        {
            "label": "",
            "sub_menu": MAIN_MENU,
            "icon": "menu",
            "is_short": True,
        },
        {
            "label": "",
            "sub_menu": {
                "title": lambda: f"Notifications ({notification_manager.unread_count})",
                "items": notification_manager.menu_items,
            },
            "color": "yellow",
            "icon": "info",
            "is_short": True,
        },
        {
            "label": "Turn off",
            "action": lambda: print("Turning off"),
            "icon": "power_settings_new",
            "is_short": True,
        },
    ],
}


class MenuApp(UboApp):
    """Menu application."""

    def build(self: MenuApp) -> Widget | None:
        Window.bind(on_keyboard=self.on_keyboard)
        return super().build()

    @cached_property
    def menu_widget(self: MenuApp) -> MenuWidget:
        """Build the main menu and initiate it."""
        menu_widget = MenuWidget()
        menu_widget.set_current_menu(HOME_MENU)

        def title_callback(_: MenuWidget, title: str):
            self.root.title = title

        self.root.title = menu_widget.title
        menu_widget.bind(title=title_callback)

        return menu_widget

    @cached_property
    def cpu_gauge(self: MenuApp) -> GaugeWidget:
        gauge = GaugeWidget(value=0, fill_color="#24D636", label="CPU")

        value = [0]

        def set_value(_dt: float) -> None:
            gauge.value = value[0]

        def calculate_value() -> None:
            value[0] = 0.3
            Clock.schedule_once(set_value)

        Clock.schedule_interval(
            lambda _dt: Thread(target=calculate_value).start(),
            1,
        )

        return gauge

    @cached_property
    def ram_gauge(self: MenuApp) -> GaugeWidget:
        gauge = GaugeWidget(
            value=50,
            fill_color="#D68F24",
            label="RAM",
        )

        def set_value(_dt: int) -> None:
            gauge.value = 60

        Clock.schedule_interval(set_value, 1)

        return gauge

    @cached_property
    def clock_widget(self: MenuApp) -> Label:
        clock = Label(font_size=dp(20))
        local_timzone = datetime.datetime.now(datetime.timezone.utc).astimezone().tzinfo

        def now() -> datetime.datetime:
            return datetime.datetime.now(local_timzone)

        def set_value(_dt: int) -> None:
            clock.text = now().strftime("%H:%M")

        set_value(0)

        def initialize(_dt: int) -> None:
            Clock.schedule_interval(set_value, 60)

        Clock.schedule_once(initialize, 60 - now().second + 1)

        return clock

    @cached_property
    def central(self: MenuApp) -> Widget:
        horizontal_layout = BoxLayout()

        self.menu_widget.size_hint = (None, 1)
        self.menu_widget.width = dp(SHORT_WIDTH)
        horizontal_layout.add_widget(self.menu_widget)

        central_column = BoxLayout(
            orientation="vertical", spacing=dp(12), padding=dp(16)
        )
        central_column.add_widget(self.cpu_gauge)
        central_column.add_widget(self.ram_gauge)
        central_column.size_hint = (1, 1)
        horizontal_layout.add_widget(central_column)

        right_column = BoxLayout(orientation="vertical")
        right_column.add_widget(VolumeWidget(value=40))
        right_column.size_hint = (None, 1)
        right_column.width = dp(SHORT_WIDTH)
        horizontal_layout.add_widget(right_column)

        def handle_depth_change(_instance: Widget, depth: int) -> None:
            if depth == 0:
                self.menu_widget.size_hint = (None, 1)
                self.menu_widget.width = dp(SHORT_WIDTH)
                central_column.size_hint = (1, 1)
                right_column.size_hint = (None, 1)
            else:
                self.menu_widget.size_hint = (1, 1)
                central_column.size_hint = (0, 1)
                right_column.size_hint = (0, 1)

        self.menu_widget.bind(depth=handle_depth_change)

        return horizontal_layout

    @cached_property
    def footer(self: MenuApp) -> Widget:
        layout = BoxLayout()

        normal_footer_layout = BoxLayout(orientation="horizontal", spacing=0, padding=0)
        normal_footer_layout.add_widget(
            Label(
                text="reply",
                font_name="material_symbols",
                font_size=dp(20),
                font_features="fill=1",
                size_hint=(None, 1),
            )
        )
        normal_footer_layout.add_widget(Widget(size_hint=(1, 1)))

        home_footer_layout = BoxLayout(orientation="horizontal", spacing=0, padding=0)
        home_footer_layout.add_widget(Widget(size_hint=(None, 1), width=dp(16)))
        home_footer_layout.add_widget(self.clock_widget)
        home_footer_layout.add_widget(Widget(size_hint=(1, 1)))

        for icon in ["camera", "lan", "mic_off", "bluetooth", "wifi_off"]:
            label = Label(
                text=icon,
                font_name="material_symbols",
                font_size=dp(20),
                font_features="fill=1",
                size_hint=(0.5, 1),
            )
            home_footer_layout.add_widget(label)
            if icon == "camera":
                label.color = "green"

        home_footer_layout.add_widget(Widget(size_hint=(None, 1), width=dp(16)))

        def handle_depth_change(_instance: Widget, depth: int) -> None:
            if depth == 0:
                if normal_footer_layout in layout.children:
                    layout.remove_widget(normal_footer_layout)
                    layout.add_widget(home_footer_layout)
            elif home_footer_layout in layout.children:
                layout.remove_widget(home_footer_layout)
                layout.add_widget(normal_footer_layout)

        self.menu_widget.bind(depth=handle_depth_change)

        layout.add_widget(home_footer_layout)

        return layout

    def on_keyboard(
        self: MenuApp,
        _: WindowBase,
        key: int,
        _scancode: int,
        _codepoint: str,
        modifier: list[Modifier],
    ) -> None:
        """Handle keyboard events."""
        if modifier == []:
            if key == Keyboard.keycodes["up"]:
                self.menu_widget.go_up()
            elif key == Keyboard.keycodes["down"]:
                self.menu_widget.go_down()
            elif key == Keyboard.keycodes["1"]:
                self.menu_widget.select(0)
            elif key == Keyboard.keycodes["2"]:
                self.menu_widget.select(1)
            elif key == Keyboard.keycodes["3"]:
                self.menu_widget.select(2)
            elif key == Keyboard.keycodes["left"]:
                self.menu_widget.go_back()


def main() -> None:
    """Instantiate the `MenuApp` and run it."""
    app = MenuApp()
    app.run()


if __name__ == "__main__":
    main()
