from __future__ import annotations

from pathlib import Path
from typing import Awaitable, Callable, Any
from typing import final


# WireGuard

async def start_wireguard_server(
    host: str,
    port: int,
    private_key: str,
    peer_public_keys: list[str],
    handle_connection: Callable[[TcpStream], Awaitable[None]],
    receive_datagram: Callable[[DatagramTransport, bytes, tuple[str, int], tuple[str, int]], None],
) -> WireGuardServer: ...

@final
class WireGuardServer:
    def getsockname(self) -> tuple[str, int]: ...
    def close(self) -> None: ...
    async def wait_closed(self) -> None: ...

def genkey() -> str: ...
def pubkey(private_key: str) -> str: ...


# Windows

async def start_os_proxy(
    handle_connection: Callable[[TcpStream], Awaitable[None]],
    receive_datagram: Callable[[DatagramTransport, bytes, tuple[str, int], tuple[str, int]], None],
) -> OsProxy: ...

@final
class OsProxy:
    @staticmethod
    def describe_spec(spec: str) -> None: ...
    def set_intercept(self, spec: str) -> None: ...
    def close(self) -> None: ...
    async def wait_closed(self) -> None: ...


# TCP / UDP

@final
class TcpStream:
    async def read(self, n: int) -> bytes: ...
    def write(self, data: bytes): ...
    async def drain(self) -> None: ...
    def write_eof(self): ...

    def close(self): ...
    def is_closing(self) -> bool: ...
    async def wait_closed(self) -> None: ...

    def get_extra_info(self, name: str, default: Any = None) -> Any: ...
    def __repr__(self) -> str: ...


@final
class DatagramTransport:
    def sendto(self, data: bytes, addr: tuple[str, int] | None = None): ...
    async def drain(self) -> None: ...

    def close(self): ...
    def is_closing(self) -> bool: ...
    async def wait_closed(self) -> None: ...

    def get_extra_info(self, name: str, default: Any = None) -> Any: ...
    def __repr__(self) -> str: ...

    def get_protocol(self) -> DatagramTransport: ...


# Process Info


def active_executables() -> list[Process]: ...
def executable_icon(path: Path | str) -> bytes: ...

@final
class Process:
    @property
    def executable(self) -> str: ...
    @property
    def display_name(self) -> str: ...
    @property
    def is_visible(self) -> bool: ...
    @property
    def is_system(self) -> bool: ...

