from datetime import datetime
from typing import Callable, Iterable

from textual._segment_tools import line_pad
from textual.app import App, ComposeResult, RenderResult
from textual.color import Color
from textual.css.styles import StylesBase
from textual.geometry import Size, Spacing
from textual.screen import Screen
from textual.strip import Strip
from textual.widgets import Digits
from rich.console import Console, ConsoleOptions
from rich.segment import Segment
from rich.style import Style
from rich.text import Text
from textual._styles_cache import StylesCache, make_blank


class TransparentBlank:
    def __rich_console__(
        self, console: Console, options: ConsoleOptions
    ) -> RenderResult:
        width = options.max_width
        height = options.height or options.max_height

        self._style = Style()

        segment = Segment(" " * width)
        line = Segment.line()
        for _ in range(height):
            yield segment
            yield line


class TransparentStyleCache(StylesCache):
    def render_line(
        self,
        styles: StylesBase,
        y: int,
        size: Size,
        content_size: Size,
        padding: Spacing,
        base_background: Color,
        background: Color,
        render_content_line: Callable[[int], Strip],
        console: Console,
        border_title: tuple[Text, Color, Color, Style] | None,
        border_subtitle: tuple[Text, Color, Color, Style] | None,
        opacity: float,
    ) -> Strip:
        gutter = styles.gutter
        width, _ = size
        content_width, content_height = content_size

        _, pad_right, _, pad_left = padding

        line: Iterable[Segment]

        content_y = y - gutter.top

        if content_y < content_height:
            line = render_content_line(y - gutter.top)
            line = line.adjust_cell_length(content_width)
        else:
            line = [make_blank(content_width)]

        line = line_pad(line, pad_left, pad_right, Style())

        strip = Strip(line, width)
        return strip


class TransparentScreen(Screen):
    def __init__(self, *args, **kwargs) -> None:
        super().__init__(*args, **kwargs)

        self._styles_cache = TransparentStyleCache()


class ClockApp(App):
    CSS = """
    App {
        background: transparent;
    }

    Screen {
        align: center middle;
        &:inline {
            border: none;
            height: 50vh;
            Digits {
                color: $success;
            }
        }
        background: transparent;
    }

    #clock {
        width: auto;
    }
    """

    def get_default_screen(self) -> Screen:
        return TransparentScreen(id="_default")

    def compose(self) -> ComposeResult:
        yield Digits("", id="clock")

    def on_ready(self) -> None:
        self.update_clock()
        self.set_interval(1, self.update_clock)

    def update_clock(self) -> None:
        clock = datetime.now().time()
        self.query_one(Digits).update(f"{clock:%T}")

    def render(self) -> RenderResult:
        return TransparentBlank()


if __name__ == "__main__":
    app = ClockApp()
    app.run(inline=True)