import asyncio
import logging

class ServidorEco:
    def __init__(self, host: str, port: int):
        self.host = host
        self.port = port
        self.nombre_clients = 0

    async def gestiona_eco(self, reader: asyncio.StreamReader, writer: asyncio.StreamWriter):
        # Incrementem el comptador d'estat de la classe
        self.nombre_clients += 1
        try:
            # Llegim dades fins que el client tanqui la connexió (EOF retorna b'')
            async for data in reader:
                # Responem amb les mateixes dades (eco)
                writer.write(data)
                # Esperem que el buffer s'enviï correctament per evitar saturació de memòria
                await writer.drain()
        except Exception as e:
            # Gestionem els errors de xarxa
            logging.exception(e)
        finally:
            # Tanquem la connexió de forma neta
            writer.close()
            await writer.wait_closed()
            # Decrementem el comptador d'estat de la classe
            self.nombre_clients -= 1

    async def serveix(self):
        # Creem el servidor passant el mètode de la instància com a callback
        server = await asyncio.start_server(self.gestiona_eco, self.host, self.port)
        
        # Utilitzem el gestor de context asíncron per garantir el tancament dels sockets
        async with server:
            # Mantenim el servidor actiu escoltant noves connexions
            await server.serve_forever()


if __name__ == "__main__":
    s = ServidorEco('127.0.0.1', 9000)
    asyncio.run(s.serveix())
