from abc import abstractmethod

from textual.binding import Binding
from textual.widget import Widget
from textual.widgets import Label


class Window(Widget):

    BINDINGS = [
        Binding("escape", "go_to_parent_window", "Go Back", show=True, priority=True),
    ]

    def __init__(self):
        """Widget representing a window in a stack of windows,
        meaning it is possible to (1) go back to the parent window
        or (2) open a child window.
        """
        self.parent_window = None
        self.label = ""
        super().__init__()

    def check_valid(self) -> bool:
        return True

    def action_go_to_parent_window(self):
        if self.parent_window is not None:
            self.remove()
            self.app.mount(self.parent_window)

    def compose(self):
        current = self
        breadcrumbs = self.label
        while current.parent_window is not None:
            current = current.parent_window
            breadcrumbs = f"{current.label} > {breadcrumbs}"

        yield Label(breadcrumbs)
        yield from self.display()

    def select_id(self, id_: str):
        window = self.get_widget(id_)

        if window is None:
            return

        try:
            window.check_valid()
        except Exception as exc:
            self.app.notify(str(exc), severity="error")
            return

        window.parent_window = self
        window.label = self.get_label(id_)
        self.remove()
        self.app.mount(window)

    @abstractmethod
    def get_widget(self, id_: str) -> "Window":
        ...

    @abstractmethod
    def get_label(self, id_: str) -> str:
        ...
