package io.quarkus.grpc.server;

import java.io.File;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.spec.JavaArchive;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.extension.RegisterExtension;

import com.google.protobuf.EmptyProtos;

import io.grpc.examples.helloworld.GreeterGrpc;
import io.grpc.examples.helloworld.HelloReply;
import io.grpc.examples.helloworld.HelloReplyOrBuilder;
import io.grpc.examples.helloworld.HelloRequest;
import io.grpc.examples.helloworld.HelloRequestOrBuilder;
import io.grpc.examples.helloworld.MutinyGreeterGrpc;
import io.grpc.netty.GrpcSslContexts;
import io.grpc.netty.NettyChannelBuilder;
import io.grpc.testing.integration.Messages;
import io.grpc.testing.integration.MutinyTestServiceGrpc;
import io.grpc.testing.integration.TestServiceGrpc;
import io.netty.handler.ssl.SslContext;
import io.quarkus.grpc.server.services.AssertHelper;
import io.quarkus.grpc.server.services.HelloService;
import io.quarkus.grpc.server.services.TestService;
import io.quarkus.test.QuarkusUnitTest;

/**
 * Test services exposed by the gRPC server implemented using the regular gRPC model.
 * Communication uses TLS and the key is loaded from the classpath.
 */
public class RegularGrpcServiceWithSSLFromClasspathTest extends GrpcServiceTestBase {

    @RegisterExtension
    static final QuarkusUnitTest config = new QuarkusUnitTest().setArchiveProducer(
            () -> ShrinkWrap.create(JavaArchive.class)
                    .addClasses(HelloService.class, TestService.class, AssertHelper.class,
                            GreeterGrpc.class, HelloRequest.class, HelloReply.class, MutinyGreeterGrpc.class,
                            HelloRequestOrBuilder.class, HelloReplyOrBuilder.class,
                            EmptyProtos.class, Messages.class, MutinyTestServiceGrpc.class,
                            TestServiceGrpc.class)
                    .addAsResource(new File("src/test/resources/tls/server-keystore.jks"), "server-keystore.jks"))
            .withConfigurationResource("grpc-server-tls-classpath-configuration.properties");

    @Override
    @BeforeEach
    public void init() throws Exception {
        SslContext sslcontext = GrpcSslContexts.forClient()
                .trustManager(createTrustAllTrustManager())
                .build();
        channel = NettyChannelBuilder.forAddress("localhost", 9000)
                .sslContext(sslcontext)
                .build();
    }

    // Create a TrustManager which trusts everything
    private static TrustManager createTrustAllTrustManager() {
        return new X509TrustManager() {
            @Override
            public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
            }

            @Override
            public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
            }

            @Override
            public X509Certificate[] getAcceptedIssuers() {
                return new X509Certificate[0];
            }
        };
    }

}
