import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;

public class HitungKoneksi {
    public static void main(String[] args) throws Exception {
        // Server HTTP tulisan tangan untuk menghitung koneksi vs permintaan
        AtomicInteger koneksi = new AtomicInteger();
        AtomicInteger permintaan = new AtomicInteger();
        AtomicReference<Socket> sambunganAktif = new AtomicReference<>();

        ServerSocket pintu = new ServerSocket(0, 1, InetAddress.getLoopbackAddress());
        Thread pegawai = new Thread(() -> {
            try {
                while (true) {
                    Socket s = pintu.accept();
                    sambunganAktif.set(s);
                    koneksi.incrementAndGet();
                    try (s;
                         BufferedReader masuk = new BufferedReader(new InputStreamReader(
                                 s.getInputStream(), StandardCharsets.ISO_8859_1));
                         PrintWriter keluar = new PrintWriter(new OutputStreamWriter(
                                 s.getOutputStream(), StandardCharsets.ISO_8859_1))) {
                        while (true) {
                            String baris = masuk.readLine();
                            if (baris == null) {
                                break; // klien menutup koneksi
                            }
                            if (!baris.isEmpty()) {
                                continue; // lewati baris header permintaan
                            }
                            permintaan.incrementAndGet();
                            // Content-Length yang tepat membuat koneksi layak dipakai ulang
                            keluar.print("HTTP/1.1 200 OK\r\n");
                            keluar.print("Content-Type: text/plain\r\n");
                            keluar.print("Content-Length: 3\r\n\r\n");
                            keluar.print("hai");
                            keluar.flush();
                        }
                    } catch (IOException e) {
                        // koneksi ditutup dari luar
                    }
                }
            } catch (IOException e) {
                // ServerSocket ditutup — pegawai selesai
            }
        });
        pegawai.start();

        try {
            HttpClient klien = HttpClient.newHttpClient();
            String url = "http://127.0.0.1:" + pintu.getLocalPort() + "/";
            for (int i = 1; i <= 3; i++) {
                HttpResponse<String> res = klien.send(
                        HttpRequest.newBuilder(URI.create(url)).GET().build(),
                        HttpResponse.BodyHandlers.ofString());
                System.out.println("permintaan " + i + " : status " + res.statusCode()
                        + ", body " + res.body());
            }
            System.out.println("koneksi dibuka  : " + koneksi.get());
            System.out.println("permintaan total: " + permintaan.get());
        } finally {
            pintu.close();
            Socket s = sambunganAktif.get();
            if (s != null) {
                s.close();
            }
            pegawai.join();
        }
    }
}
