from collections.abc import Callable, Container
from types import TracebackType
from typing import Generic, Literal, ParamSpec, Protocol, TypeAlias, type_check_only
from typing_extensions import Self, TypeVarTuple, Unpack

from gevent._types import _Loop
from gevent.pool import Pool
from gevent.socket import socket as _GeventSocket
from greenlet import greenlet

_Ts = TypeVarTuple("_Ts")
_P = ParamSpec("_P")

@type_check_only
class _SpawnFunc(Protocol):
    def __call__(self, func: Callable[_P, object], /, *args: _P.args, **kwargs: _P.kwargs) -> greenlet: ...

_Spawner: TypeAlias = Pool | _SpawnFunc | int | Literal["default"] | None

class BaseServer(Generic[Unpack[_Ts]]):
    min_delay: float
    max_delay: float
    max_accept: int
    stop_timeout: float
    fatal_errors: Container[int]
    pool: Pool | None
    delay: float
    loop: _Loop
    family: int
    address: str | tuple[str, int]
    socket: _GeventSocket
    handle: Callable[[Unpack[_Ts]], object]
    def __init__(
        self,
        listener: _GeventSocket | tuple[str, int] | str,
        handle: Callable[[Unpack[_Ts]], object] | None = None,
        spawn: _Spawner = "default",
    ) -> None: ...
    def __enter__(self) -> Self: ...
    def __exit__(self, typ: type[BaseException] | None, value: BaseException | None, tb: TracebackType | None, /) -> None: ...
    def set_listener(self, listener: _GeventSocket | tuple[str, int] | str) -> None: ...
    def set_spawn(self, spawn: _Spawner) -> None: ...
    def set_handle(self, handle: Callable[[Unpack[_Ts]], object]) -> None: ...
    def start_accepting(self) -> None: ...
    def stop_accepting(self) -> None: ...
    def do_handle(self, *args: Unpack[_Ts]) -> None: ...
    def do_close(self, *args: Unpack[_Ts]) -> None: ...
    def do_read(self) -> tuple[Unpack[_Ts]] | None: ...
    def full(self) -> bool: ...
    @property
    def server_host(self) -> str | None: ...
    @property
    def server_port(self) -> int | None: ...
    def init_socket(self) -> None: ...
    @property
    def started(self) -> bool: ...
    def start(self) -> None: ...
    def close(self) -> None: ...
    @property
    def closed(self) -> bool: ...
    def stop(self, timeout: float | None = None) -> None: ...
    def serve_forever(self, stop_timeout: float | None = None) -> None: ...
    def is_fatal_error(self, ex: BaseException) -> bool: ...

__all__ = ["BaseServer"]
