import socket
from asyncio import AbstractEventLoop, Event, Future, Task
from threading import Thread
from typing import Any, Dict, Optional

from asyncpg import cluster as cluster

class StopServer(Exception): ...

class TCPFuzzingProxy:
    listening_addr: str = ...
    listening_port: Optional[int] = ...
    backend_host: str = ...
    backend_port: int = ...
    settings: Dict[str, Any] = ...
    loop: Optional[AbstractEventLoop] = ...
    connectivity: Optional[Event] = ...
    connectivity_loss: Optional[Event] = ...
    stop_event: Optional[Event] = ...
    connections: Dict[Connection, Task[Any]] = ...
    sock: Optional[socket.socket] = ...
    listen_task: Optional[Future[Any]] = ...
    def __init__(
        self,
        *,
        listening_addr: str = ...,
        listening_port: Optional[int] = ...,
        backend_host: str,
        backend_port: int,
        settings: Optional[Dict[str, Any]] = ...,
    ) -> None: ...
    thread: Optional[Thread] = ...
    def start(self) -> None: ...
    def stop(self) -> None: ...
    async def listen(self) -> None: ...
    def trigger_connectivity_loss(self) -> None: ...
    def restore_connectivity(self) -> None: ...
    def reset(self) -> None: ...
    def close_all_connections(self) -> None: ...

class Connection:
    client_sock: socket.socket = ...
    backend_sock: socket.socket = ...
    proxy: TCPFuzzingProxy = ...
    loop: AbstractEventLoop = ...
    connectivity: Event = ...
    connectivity_loss: Event = ...
    proxy_to_backend_task: Optional[Future[Any]] = ...
    proxy_from_backend_task: Optional[Future[Any]] = ...
    is_closed: bool = ...
    def __init__(
        self,
        client_sock: socket.socket,
        backend_sock: socket.socket,
        proxy: TCPFuzzingProxy,
    ) -> None: ...
    def close(self) -> None: ...
    async def handle(self) -> None: ...
    async def proxy_to_backend(self) -> None: ...
    async def proxy_from_backend(self) -> None: ...
