from typing import (
    Callable, Union, overload, Optional)

UDP: int
UNIX: int
TCP: int


class Message:
    path: str
    args: list[int | float | str | bytes]
    types: str
    
    def __init__(self, path: str, *args: tuple) -> None: ...
    def deserialise(self, buf) -> 'Message': ...
    def serialise(self): ...
    def add(self, *args: tuple): ...


class Bundle:
    @overload
    def __init__(self, timetag: float, *messages: tuple[Message]) -> None: ...
    @overload
    def __init__(self, *messages: tuple[Message]): ...

    @overload
    def add(self, path: str, *messages: tuple[Message]): ...
    @overload
    def add(self, *args: tuple): ...


class Address:
    url: str
    hostname: str
    port: Union[int, str]
    protocol: int
    
    @overload
    def __init__(self, hostname: str, port: Union[int, str], proto: int =UDP): ...
    @overload
    def __init__(self, port: Union[int, str]): ...
    @overload
    def __init__(self, url: str): ...


class __AbstractServer:
    url: str
    port: Union[int, str]
    protocol: int
    
    def __init__(self, port: Union[int, str] =1, proto: int =UDP, reg_methods=True): ...
    def recv(self, timeout: Optional[int] =None) -> bool: ...
    def add_method(self, path: str | None, typespec: str | None, func: Callable, user_data=None): ...
    def del_method(self, path: str | None, typespec: str | None): ...
    def register_methods(self, obj=None): ...
    def add_bundle_handlers(
        self, start_handler: Callable, end_handler: Callable, user_data=None): ...
    
    @overload
    def send(self, address: Address | str | int, path: str, *args: tuple): ...
    @overload
    def send(self, address: Address | str | int, *messages: tuple[Message]): ...

    def fileno(self) -> int: ...
    def free(self): ...


class Server(__AbstractServer):
    def recv(self, timeout: Optional[int] =None) -> bool: ...


class ServerThread(__AbstractServer):
    def start(self): ...
    def stop(self): ...


class ServerError(BaseException): ...


class AddressError(BaseException): ...


@overload
def send(target: Union[Address, int, tuple[str, int], str],
         path: str,
         *args: tuple): ...
@overload
def send(target: Union[Address, int, tuple[str, int], str],
         *messages: tuple[Message]): ...

def time() -> float: ...
def make_method(path: str, typespec: str, user_data=None): ...
