from __future__ import annotations

from typing import Any, Callable, Protocol


class PluginPanel(Protocol):
    def clear(self) -> None: ...
    def add_label(self, text: str) -> None: ...
    def set_text(self, text: str) -> None: ...
    def set_html(self, html: str) -> None: ...
    def add_button(self, text: str, action_path: str | None = None) -> None: ...
    def add_button_callback(self, text: str, callback: Callable[[], Any]) -> None: ...
    def add_label_named(self, key: str, text: str) -> None: ...
    def set_label_text(self, key: str, text: str) -> bool: ...
    def add_int_field(self, key: str, label: str, value: int, min: int = 0, max: int = 999999) -> None: ...
    def add_float_field(
        self,
        key: str,
        label: str,
        value: float,
        min: float = -1e9,
        max: float = 1e9,
        decimals: int = 3,
        step: float = 1.0,
    ) -> None: ...
    def get_int_field(self, key: str) -> int: ...
    def get_float_field(self, key: str) -> float: ...


class Transaction(Protocol):
    def commit(self) -> bool: ...
    def cancel(self) -> None: ...
    def rollback(self) -> None: ...
    def __enter__(self) -> Transaction: ...
    def __exit__(self, exc_type: type[BaseException] | None, exc: BaseException | None, tb: Any) -> bool | None: ...


class Entity(Protocol):
    @property
    def classname(self) -> str: ...
    def keys(self) -> list[str]: ...
    def get(self, key: str, default: Any = None) -> Any: ...


class Selection(Protocol):
    @property
    def entities(self) -> list[Entity]: ...
    @property
    def all_entities(self) -> list[Entity]: ...
    def set_property(self, key: str, value: str, default_to_protected: bool = False) -> bool: ...
    def remove_property(self, key: str) -> bool: ...
    def rename_property(self, old_key: str, new_key: str) -> bool: ...
    def clear(self) -> None: ...
    def duplicate(self) -> None: ...
    def translate(self, x: float, y: float, z: float) -> bool: ...
    def rotate(
        self,
        axis_x: float,
        axis_y: float,
        axis_z: float,
        angle_degrees: float,
        center_x: float | None = None,
        center_y: float | None = None,
        center_z: float | None = None,
    ) -> bool: ...
    def brush_vertices(self) -> list[list[tuple[float, float, float]]]: ...


class Document(Protocol):
    @classmethod
    def current(cls) -> Document | None: ...

    @property
    def selection(self) -> Selection: ...

    def get_selection(self) -> Selection: ...
    def transaction(self, name: str = "Python Script") -> Transaction: ...
    def vertex_tool_vertices(self) -> list[tuple[float, float, float]]: ...


def current_document() -> Document | None:
    raise RuntimeError('Module "tb" is only available inside TrenchBroom.')


def document() -> Document:
    raise RuntimeError('Module "tb" is only available inside TrenchBroom.')


def transaction(name: str = "Python Script") -> Transaction:
    raise RuntimeError('Module "tb" is only available inside TrenchBroom.')


def execute_action(path: str) -> None:
    raise RuntimeError('Module "tb" is only available inside TrenchBroom.')


def list_actions() -> list[str]:
    raise RuntimeError('Module "tb" is only available inside TrenchBroom.')


def add_plugin_panel(title: str, content: str | None = None) -> None:
    raise RuntimeError('Module "tb" is only available inside TrenchBroom.')


def create_plugin_panel(title: str) -> PluginPanel:
    raise RuntimeError('Module "tb" is only available inside TrenchBroom.')


__all__ = [
    "Document",
    "Entity",
    "PluginPanel",
    "Selection",
    "Transaction",
    "add_plugin_panel",
    "create_plugin_panel",
    "current_document",
    "document",
    "execute_action",
    "list_actions",
    "transaction",
]
