/*
 * Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

/*
 * @test
 * @summary Tests mapped response subscriber
 * @library /test/lib /test/jdk/java/net/httpclient/lib
 * @build jdk.test.lib.net.SimpleSSLContext jdk.httpclient.test.lib.http2.Http2TestServer
 *        jdk.httpclient.test.lib.common.TestServerConfigurator
 * @run testng/othervm
 *       -Djdk.internal.httpclient.debug=true
 *      MappingResponseSubscriber
 */

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.URI;
import java.nio.ByteBuffer;
import java.util.List;
import java.util.concurrent.CompletionStage;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.Flow;
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpServer;
import com.sun.net.httpserver.HttpsServer;
import java.net.http.HttpClient;
import java.net.http.HttpHeaders;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.http.HttpResponse.BodyHandler;
import java.net.http.HttpResponse.BodyHandlers;
import java.net.http.HttpResponse.BodySubscribers;
import  java.net.http.HttpResponse.BodySubscriber;
import java.util.function.Function;
import javax.net.ssl.SSLContext;

import jdk.httpclient.test.lib.common.TestServerConfigurator;
import jdk.internal.net.http.common.OperationTrackers.Tracker;
import jdk.httpclient.test.lib.http2.Http2TestServer;
import jdk.httpclient.test.lib.http2.Http2TestExchange;
import jdk.httpclient.test.lib.http2.Http2Handler;
import jdk.test.lib.net.SimpleSSLContext;
import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import static java.lang.System.out;
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertTrue;

public class MappingResponseSubscriber {

    SSLContext sslContext;
    HttpServer httpTestServer;         // HTTP/1.1    [ 4 servers ]
    HttpsServer httpsTestServer;       // HTTPS/1.1
    Http2TestServer http2TestServer;   // HTTP/2 ( h2c )
    Http2TestServer https2TestServer;  // HTTP/2 ( h2  )
    String httpURI_fixed;
    String httpURI_chunk;
    String httpsURI_fixed;
    String httpsURI_chunk;
    String http2URI_fixed;
    String http2URI_chunk;
    String https2URI_fixed;
    String https2URI_chunk;

    static final int ITERATION_COUNT = 3;
    // a shared executor helps reduce the amount of threads created by the test
    static final Executor executor = Executors.newCachedThreadPool();

    static final ReferenceTracker TRACKER = ReferenceTracker.INSTANCE;

    @DataProvider(name = "variants")
    public Object[][] variants() {
        return new Object[][]{
                { httpURI_fixed,    false },
                { httpURI_chunk,    false },
                { httpsURI_fixed,   false },
                { httpsURI_chunk,   false },
                { http2URI_fixed,   false },
                { http2URI_chunk,   false },
                { https2URI_fixed,  false,},
                { https2URI_chunk,  false },

                { httpURI_fixed,    true },
                { httpURI_chunk,    true },
                { httpsURI_fixed,   true },
                { httpsURI_chunk,   true },
                { http2URI_fixed,   true },
                { http2URI_chunk,   true },
                { https2URI_fixed,  true,},
                { https2URI_chunk,  true },
        };
    }

    HttpClient newHttpClient() {
        return HttpClient.newBuilder()
                         .executor(executor)
                         .sslContext(sslContext)
                         .build();
    }

    @Test(dataProvider = "variants")
    public void testAsBytes(String uri, boolean sameClient) throws Exception {
        HttpClient client = null;
        for (int i = 0; i < ITERATION_COUNT; i++) {
            if (!sameClient || client == null)
                client = newHttpClient();

            HttpRequest req = HttpRequest.newBuilder(URI.create(uri))
                    .build();
            BodyHandler<byte[]> handler = new CRSBodyHandler();
            HttpResponse<byte[]> response = client.send(req, handler);
            byte[] body = response.body();
            assertEquals(body, bytes);

            // if sameClient we will reuse the client for the next
            // operation, so there's nothing more to do.
            if (sameClient) continue;

            // if no error and not same client then wait for the
            // client to be GC'ed before performing the nex operation
            Tracker tracker = TRACKER.getTracker(client);
            client = null;
            System.gc();
            AssertionError error = TRACKER.check(tracker, 1500);
            if (error != null) throw error; // the client didn't shut down properly
        }
        if (sameClient) {
            Tracker tracker = TRACKER.getTracker(client);
            client = null;
            System.gc();
            AssertionError error = TRACKER.check(tracker,1500);
            if (error != null) throw error; // the client didn't shut down properly
        }
    }

    static class CRSBodyHandler implements BodyHandler<byte[]> {
        @Override
        public BodySubscriber<byte[]> apply(HttpResponse.ResponseInfo rinfo) {
            assertEquals(rinfo.statusCode(), 200);
            return BodySubscribers.mapping(
                new CRSBodySubscriber(), (s) -> s.getBytes(UTF_8)
            );
        }
    }

    static class CRSBodySubscriber implements BodySubscriber<String> {
        private final BodySubscriber<String> ofString = BodySubscribers.ofString(UTF_8);
        volatile boolean onSubscribeCalled;

        @Override
        public void onSubscribe(Flow.Subscription subscription) {
            //out.println("onSubscribe ");
            onSubscribeCalled = true;
            ofString.onSubscribe(subscription);
        }

        @Override
        public void onNext(List<ByteBuffer> item) {
           // out.println("onNext " + item);
            assertTrue(onSubscribeCalled);
            ofString.onNext(item);
        }

        @Override
        public void onError(Throwable throwable) {
            //out.println("onError");
            assertTrue(onSubscribeCalled);
            ofString.onError(throwable);
        }

        @Override
        public void onComplete() {
            //out.println("onComplete");
            assertTrue(onSubscribeCalled, "onComplete called before onSubscribe");
            ofString.onComplete();
        }

        @Override
        public CompletionStage<String> getBody() {
            return ofString.getBody();
        }
    }

    static String serverAuthority(HttpServer server) {
        return InetAddress.getLoopbackAddress().getHostName() + ":"
                + server.getAddress().getPort();
    }

    @BeforeTest
    public void setup() throws Exception {
        sslContext = new SimpleSSLContext().get();
        if (sslContext == null)
            throw new AssertionError("Unexpected null sslContext");

        // HTTP/1.1
        HttpHandler h1_fixedLengthHandler = new HTTP1_FixedLengthHandler();
        HttpHandler h1_chunkHandler = new HTTP1_ChunkedHandler();
        InetSocketAddress sa = new InetSocketAddress(InetAddress.getLoopbackAddress(), 0);
        httpTestServer = HttpServer.create(sa, 0);
        httpTestServer.createContext("/http1/fixed", h1_fixedLengthHandler);
        httpTestServer.createContext("/http1/chunk", h1_chunkHandler);
        httpURI_fixed = "http://" + serverAuthority(httpTestServer) + "/http1/fixed";
        httpURI_chunk = "http://" + serverAuthority(httpTestServer) + "/http1/chunk";

        httpsTestServer = HttpsServer.create(sa, 0);
        httpsTestServer.setHttpsConfigurator(new TestServerConfigurator(sa.getAddress(), sslContext));
        httpsTestServer.createContext("/https1/fixed", h1_fixedLengthHandler);
        httpsTestServer.createContext("/https1/chunk", h1_chunkHandler);
        httpsURI_fixed = "https://" + serverAuthority(httpsTestServer) + "/https1/fixed";
        httpsURI_chunk = "https://" + serverAuthority(httpsTestServer) + "/https1/chunk";

        // HTTP/2
        Http2Handler h2_fixedLengthHandler = new HTTP2_FixedLengthHandler();
        Http2Handler h2_chunkedHandler = new HTTP2_VariableHandler();

        http2TestServer = new Http2TestServer("localhost", false, 0);
        http2TestServer.addHandler(h2_fixedLengthHandler, "/http2/fixed");
        http2TestServer.addHandler(h2_chunkedHandler, "/http2/chunk");
        http2URI_fixed = "http://" + http2TestServer.serverAuthority() + "/http2/fixed";
        http2URI_chunk = "http://" + http2TestServer.serverAuthority() + "/http2/chunk";

        https2TestServer = new Http2TestServer("localhost", true, sslContext);
        https2TestServer.addHandler(h2_fixedLengthHandler, "/https2/fixed");
        https2TestServer.addHandler(h2_chunkedHandler, "/https2/chunk");
        https2URI_fixed = "https://" + https2TestServer.serverAuthority() + "/https2/fixed";
        https2URI_chunk = "https://" + https2TestServer.serverAuthority() + "/https2/chunk";

        httpTestServer.start();
        httpsTestServer.start();
        http2TestServer.start();
        https2TestServer.start();
    }

    @AfterTest
    public void teardown() throws Exception {
        httpTestServer.stop(0);
        httpsTestServer.stop(0);
        http2TestServer.stop();
        https2TestServer.stop();
    }

    static byte[] bytes;

    static {
        bytes = new byte[128 * 1024];
        int b = 'A';

        for (int i=0; i< bytes.length; i++) {
            bytes[i] = (byte)b;
            b = b == 'Z'? 'A' : b + 1;
        }
    }

    static class HTTP1_FixedLengthHandler implements HttpHandler {
        @Override
        public void handle(HttpExchange t) throws IOException {
            out.println("HTTP1_FixedLengthHandler received request to " + t.getRequestURI());
            try (InputStream is = t.getRequestBody()) {
                is.readAllBytes();
            }
            t.sendResponseHeaders(200, bytes.length);  //no body
            OutputStream os = t.getResponseBody();
            os.write(bytes);
            os.close();
        }
    }

    static class HTTP1_ChunkedHandler implements HttpHandler {
        @Override
        public void handle(HttpExchange t) throws IOException {
            out.println("HTTP1_ChunkedHandler received request to " + t.getRequestURI());
            try (InputStream is = t.getRequestBody()) {
                is.readAllBytes();
            }
            t.sendResponseHeaders(200, 0); // chunked
            OutputStream os = t.getResponseBody();
            os.write(bytes);
            os.close();
        }
    }

    static class HTTP2_FixedLengthHandler implements Http2Handler {
        @Override
        public void handle(Http2TestExchange t) throws IOException {
            out.println("HTTP2_FixedLengthHandler received request to " + t.getRequestURI());
            try (InputStream is = t.getRequestBody()) {
                is.readAllBytes();
            }
            t.sendResponseHeaders(200, 0); // chunked
            OutputStream os = t.getResponseBody();
            os.write(bytes);
            os.close();
        }
    }

    static class HTTP2_VariableHandler implements Http2Handler {
        @Override
        public void handle(Http2TestExchange t) throws IOException {
            out.println("HTTP2_VariableHandler received request to " + t.getRequestURI());
            try (InputStream is = t.getRequestBody()) {
                is.readAllBytes();
            }
            t.sendResponseHeaders(200, bytes.length);  //no body
            OutputStream os = t.getResponseBody();
            os.write(bytes);
            os.close();
        }
    }

    // -- Compile only. Verifies generic signatures

    static final Function<CharSequence,Integer> f1 = subscriber -> 1;
    static final Function<CharSequence,Number> f2 = subscriber -> 2;
    static final Function<String,Integer> f3 = subscriber -> 3;
    static final Function<String,Number> f4 = subscriber -> 4;

    public void compileOnly() throws Exception {
        HttpClient client = null;
        HttpRequest req = null;

        HttpResponse<Integer> r1 = client.send(req, (ri) ->
                BodySubscribers.mapping(BodySubscribers.ofString(UTF_8), s -> 1));
        HttpResponse<Number>  r2 = client.send(req, (ri) ->
                BodySubscribers.mapping(BodySubscribers.ofString(UTF_8), s -> 1));
        HttpResponse<String>  r3 = client.send(req, (ri) ->
                BodySubscribers.mapping(BodySubscribers.ofString(UTF_8), s -> "s"));
        HttpResponse<CharSequence> r4 = client.send(req, (ri) ->
                BodySubscribers.mapping(BodySubscribers.ofString(UTF_8), s -> "s"));

        HttpResponse<Integer> x1 = client.send(req, (ri) ->
                BodySubscribers.mapping(BodySubscribers.ofString(UTF_8), f1));
        HttpResponse<Number>  x2 = client.send(req, (ri) ->
                BodySubscribers.mapping(BodySubscribers.ofString(UTF_8), f1));
        HttpResponse<Number>  x3 = client.send(req, (ri) ->
                BodySubscribers.mapping(BodySubscribers.ofString(UTF_8), f2));
        HttpResponse<Integer> x4 = client.send(req, (ri) ->
                BodySubscribers.mapping(BodySubscribers.ofString(UTF_8), f3));
        HttpResponse<Number>  x5 = client.send(req, (ri) ->
                BodySubscribers.mapping(BodySubscribers.ofString(UTF_8), f3));
        HttpResponse<Number>  x7 = client.send(req, (ri) ->
                BodySubscribers.mapping(BodySubscribers.ofString(UTF_8), f4));
    }
}
