from pathlib import Path

from rich.syntax import Syntax

from textual.app import App, ComposeResult
from textual.command import Hit, Hits, Provider
from textual.containers import VerticalScroll
from textual.widgets import Static


class PythonFileCommands(Provider):
    """A command provider to open a Python file in the current working directory."""

    def read_files(self) -> list[Path]:
        """Get a list of Python files in the current working directory."""
        return list(Path("./").glob("*.py"))

    async def startup(self) -> None:  # (1)!
        """Called once when the command palette is opened, prior to searching."""
        worker = self.app.run_worker(self.read_files, thread=True)
        self.python_paths = await worker.wait()

    async def search(self, query: str) -> Hits:  # (2)!
        """Search for Python files."""
        matcher = self.matcher(query)  # (3)!

        app = self.app
        assert isinstance(app, ViewerApp)

        for path in self.python_paths:
            command = f"open {str(path)}"
            score = matcher.match(command)  # (4)!
            if score > 0:
                yield Hit(
                    score,
                    matcher.highlight(command),  # (5)!
                    lambda: app.open_file(path),
                    help="Open this file in the viewer",
                )


class ViewerApp(App):
    """Demonstrate a command source."""

    COMMANDS = App.COMMANDS | {PythonFileCommands}  # (6)!

    def compose(self) -> ComposeResult:
        with VerticalScroll():
            yield Static(id="code", expand=True)

    def open_file(self, path: Path) -> None:
        """Open and display a file with syntax highlighting."""
        syntax = Syntax.from_path(
            str(path),
            line_numbers=True,
            word_wrap=False,
            indent_guides=True,
            theme="github-dark",
        )
        self.query_one("#code", Static).update(syntax)


if __name__ == "__main__":
    app = ViewerApp()
    app.run()
