import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousChannelGroup;
import java.nio.channels.AsynchronousServerSocketChannel;
import java.nio.channels.AsynchronousSocketChannel;
import java.nio.channels.CompletionHandler;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.Future;

public class AsyncEchoServer {
    public static void main(String[] args) throws Exception {
        AsynchronousChannelGroup group = AsynchronousChannelGroup.withCachedThreadPool(Executors.newCachedThreadPool(), 10);

        AsynchronousServerSocketChannel serverChannel = AsynchronousServerSocketChannel.open(group)
                .bind(new InetSocketAddress("localhost", 4711));

        serverChannel.accept(null, new CompletionHandler<AsynchronousSocketChannel, Object>() {
            @Override
            public void completed(AsynchronousSocketChannel socketChannel, Object attachment) {
                serverChannel.accept(null, this); // Akzeptiere weitere Verbindungen

                handle(socketChannel);
            }

            @Override
            public void failed(Throwable exc, Object attachment) {
                System.err.println("Failed to accept a connection.");
                exc.printStackTrace();
            }
        });

        group.awaitTermination(Long.MAX_VALUE, TimeUnit.SECONDS);
    }

    private static void handle(AsynchronousSocketChannel socketChannel) {
        ByteBuffer buffer = ByteBuffer.allocate(1024);

        try {
            while (true) {
                Future<Integer> readResult = socketChannel.read(buffer);
                int bytesRead = readResult.get(); // Blockiert bis Daten gelesen werden

                if (bytesRead == -1) break;

                buffer.flip();
                String input = new String(buffer.array(), 0, bytesRead);
                System.out.println("Received: " + input);

                // Verarbeite die Eingabe und sende eine Antwort zurück
                ByteBuffer outputBuffer = ByteBuffer.wrap(input.toUpperCase().getBytes());
                socketChannel.write(outputBuffer);

                buffer.clear();
            }
        } catch (Exception e) {
            System.err.println("Connection handler encountered an error:");
            e.printStackTrace();
        }
    }
}