// 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.InetSocketAddress;
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 javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;

import com.sun.net.httpserver.HttpServer;

import tech.kwik.core.log.SysOutLogger;
import tech.kwik.core.server.ServerConnector;
import tech.kwik.flupke.server.Http3ApplicationProtocolFactory;

public class UntrustedHttp3 {

  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();

    // http1 server on tcp 8080
    // btw what if we made a conveniece method? I'll contribute it myself, just say the word
    var http1 = HttpServer.create(new InetSocketAddress(8080), 0);
    http1.createContext("/", ctx -> ctx.sendResponseHeaders(101, -1));
    http1.start();

    // 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) -> {
              IO.println("Yeah buddy");
              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);
      // freezes forever
      HttpClient.newBuilder()
          .version(Version.HTTP_3)
          .sslContext(sslContext)
          .build()
          .send(
              HttpRequest.newBuilder().uri(URI.create("https://localhost:8080")).GET().build(),
              BodyHandlers.ofString())
          .body();
      IO.println("End");
    } finally {
      connector.close();
      http1.stop(0);
    }
  }
}
