// DEPS tech.kwik:kwik:0.10.7
// DEPS tech.kwik:kwik-qlog:0.10.7
// DEPS tech.kwik:flupke:0.9

// Install mkcert with Chocolatey == choco install mkcert
// Install CA root ================= mkcert -install
// Create cert for localhost ======= mkcert localhost 127.0.0.1 ::1
// Find CA root path =============== mkcert -caroot
//
// Create PKCS12 keystore for Java ================================
// openssl pkcs12 -export   -out "keystore.p12"   -inkey "${KEY_FILE}"   -in "${CERT_FILE}"
// -name "somealias"   -certfile "$(mkcert -CAROOT)/rootCA.pem"
// ================================================================
//

import static java.nio.charset.StandardCharsets.UTF_8;
import static java.nio.file.Files.newInputStream;

import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpClient.Version;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse.BodyHandlers;
import java.nio.file.Path;
import java.security.KeyStore;
import java.time.Duration;

import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;

import tech.kwik.core.log.SysOutLogger;
import tech.kwik.core.server.ServerConnector;
import tech.kwik.flupke.server.Http3ApplicationProtocolFactory;

public class Timeout {

  void main() throws Exception {
    var keystore = KeyStore.getInstance("PKCS12");

    var password = "password";

    keystore.load(newInputStream(Path.of("keystore.p12")), password.toCharArray());

    var certificateAlias = keystore.aliases().nextElement();

    // http3 server on udp 8080
    var connector =
        ServerConnector.builder()
            .withLogger(new SysOutLogger())
            .withPort(8080)
            .withKeyStore(keystore, certificateAlias, password.toCharArray())
            .build();

    var factory =
        new Http3ApplicationProtocolFactory(
            (request, response) -> {
              try {
                Thread.sleep(Duration.ofSeconds(40));
              } catch (InterruptedException e) {
                Thread.interrupted();
              }
              response.setStatus(200);

              var stream = response.getOutputStream();
              stream.write("Hello, world!".getBytes(UTF_8));
              stream.flush();
            });

    connector.registerApplicationProtocol("h3", factory);
    connector.start();
    try {
      var kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());

      kmf.init(keystore, password.toCharArray());

      var sslContext = SSLContext.getInstance("TLS");

      sslContext.init(kmf.getKeyManagers(), null, null);
      var response =
          HttpClient.newBuilder()
              .version(Version.HTTP_3)
              .sslContext(sslContext)
              .build()
              .send(
                  HttpRequest.newBuilder()
                      .timeout(Duration.ofSeconds(45))
                      .uri(URI.create("https://localhost:8080"))
                      .GET()
                      .build(),
                  BodyHandlers.ofString())
              .body();
      assert "Hello, world!".equals(response);
    } finally {
      connector.close();
    }
  }
}
