import selectors
from selectors import SelectorKey
from typing import List, Tuple
import socket
import asyncio
from asyncio import AbstractEventLoop
import logging


async def echo(connection: socket, loop: AbstractEventLoop) -> None:
    try:
        while data := await loop.sock_recv(connection, 1024):
            if data == b'q':
                raise Exception('Неожиданая ошибка сети')
            await loop.sock_sendall(connection, data)
    except Exception as ex:
        logging.exception(ex)
    finally:
        connection.close()


async def listen_for_connections(server_socket: socket, loop: AbstractEventLoop):
    while True:
        connection, address = await loop.sock_accept(server_socket)
        connection.setblocking(False)
        print(f'Получен запрос на подключение от {address}')
        asyncio.create_task(echo(connection, loop))


async def main():
    server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    
    server_address = ('127.0.0.1', 8000)
    server_socket.setblocking(False)
    server_socket.bind(server_address)
    server_socket.listen()
    
    await listen_for_connections(server_socket, asyncio.get_event_loop())
    # asyncio.run(main())


def foo():

    selector = selectors.DefaultSelector()

    server_socket = socket.socket()
    server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    
    server_address = ('127.0.0.1', 8000)
    server_socket.setblocking(False)
    server_socket.bind(server_address)
    server_socket.listen()

    selector.register(server_socket, selectors.EVENT_READ)

    while True:
        events: List[Tuple[SelectorKey, int]] = selector.select(timeout=1)

        if len(events) == 0:
            print('Событий нет, подожду еще!')

        for event, _ in events:
            event_socket = event.fileobj

            if event_socket == server_socket:
                connection, address = server_socket.accept()
                connection.setblocking(False)
                print(f'Получен запрос на подключение от {address}')
                selector.register(connection, selectors.EVENT_READ)
            else:
                data = event_socket.recv(1024)
                print(f"Получены данные: {data}")
                event_socket.send(data)


if __name__ == '__main__':
    asyncio.run(main())