/*
 * Copyright (c) 2016, 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.
 */

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpHeaders;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Optional;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;
import java.util.concurrent.Flow;
import java.util.stream.Stream;
import static java.lang.System.err;

/*
 * @test
 * @summary An example on how to read a response body with InputStream.
 * @run main/othervm/manual -Dtest.debug=true HttpInputStreamTest
 * @author daniel fuchs
 */
public class HttpInputStreamTest {

    public static boolean DEBUG = Boolean.getBoolean("test.debug");

    /**
     * A simple HttpResponse.BodyHandler that creates a live
     * InputStream to read the response body from the underlying ByteBuffer
     * Flow.
     * The InputStream is made immediately available for consumption, before
     * the response body is fully received.
     */
    public static class HttpInputStreamHandler
        implements HttpResponse.BodyHandler<InputStream>    {

        public static final int MAX_BUFFERS_IN_QUEUE = 1;  // lock-step with the producer

        private final int maxBuffers;

        public HttpInputStreamHandler() {
            this(MAX_BUFFERS_IN_QUEUE);
        }

        public HttpInputStreamHandler(int maxBuffers) {
            this.maxBuffers = maxBuffers <= 0 ? MAX_BUFFERS_IN_QUEUE : maxBuffers;
        }

        @Override
        public HttpResponse.BodySubscriber<InputStream>
                apply(HttpResponse.ResponseInfo rinfo) {
            return new HttpResponseInputStream(maxBuffers);
        }

        /**
         * An InputStream built on top of the Flow API.
         */
        private static class HttpResponseInputStream extends InputStream
                    implements HttpResponse.BodySubscriber<InputStream> {

            // An immutable ByteBuffer sentinel to mark that the last byte was received.
            private static final ByteBuffer LAST_BUFFER = ByteBuffer.wrap(new byte[0]);
            private static final List<ByteBuffer> LAST_LIST = List.of(LAST_BUFFER);

            // A queue of yet unprocessed ByteBuffers received from the flow API.
            private final BlockingQueue<List<ByteBuffer>> buffers;
            private volatile Flow.Subscription subscription;
            private volatile boolean closed;
            private volatile Throwable failed;
            private volatile Iterator<ByteBuffer> currentListItr;
            private volatile ByteBuffer currentBuffer;

            HttpResponseInputStream() {
                this(MAX_BUFFERS_IN_QUEUE);
            }

            HttpResponseInputStream(int maxBuffers) {
                int capacity = maxBuffers <= 0 ? MAX_BUFFERS_IN_QUEUE : maxBuffers;
                // 1 additional slot for LAST_LIST added by onComplete
                this.buffers = new ArrayBlockingQueue<>(capacity + 1);
            }

            @Override
            public CompletionStage<InputStream> getBody() {
                // Return the stream immediately, before the
                // response body is received.
                // This makes it possible for senAsync().get().body()
                // to complete before the response body is received.
                return CompletableFuture.completedStage(this);
            }

            // Returns the current byte buffer to read from.
            // If the current buffer has no remaining data, will take the
            // next buffer from the buffers queue, possibly blocking until
            // a new buffer is made available through the Flow API, or the
            // end of the flow is reached.
            private ByteBuffer current() throws IOException {
                while (currentBuffer == null || !currentBuffer.hasRemaining()) {
                    // Check whether the stream is closed or exhausted
                    if (closed || failed != null) {
                        throw new IOException("closed", failed);
                    }
                    if (currentBuffer == LAST_BUFFER) break;

                    try {
                        if (currentListItr == null || !currentListItr.hasNext()) {
                            // Take a new list of buffers from the queue, blocking
                            // if none is available yet...

                            if (DEBUG) err.println("Taking list of Buffers");
                            List<ByteBuffer> lb = buffers.take();
                            currentListItr = lb.iterator();
                            if (DEBUG) err.println("List of Buffers Taken");

                            // Check whether an exception was encountered upstream
                            if (closed || failed != null)
                                throw new IOException("closed", failed);

                            // Check whether we're done.
                            if (lb == LAST_LIST) {
                                currentListItr = null;
                                currentBuffer = LAST_BUFFER;
                                break;
                            }

                            // Request another upstream item ( list of buffers )
                            Flow.Subscription s = subscription;
                            if (s != null)
                                s.request(1);
                        }
                        assert currentListItr != null;
                        assert currentListItr.hasNext();
                        if (DEBUG) err.println("Next Buffer");
                        currentBuffer = currentListItr.next();
                    } catch (InterruptedException ex) {
                        // continue
                    }
                }
                assert currentBuffer == LAST_BUFFER || currentBuffer.hasRemaining();
                return currentBuffer;
            }

            @Override
            public int read(byte[] bytes, int off, int len) throws IOException {
                // get the buffer to read from, possibly blocking if
                // none is available
                ByteBuffer buffer;
                if ((buffer = current()) == LAST_BUFFER) return -1;

                // don't attempt to read more than what is available
                // in the current buffer.
                int read = Math.min(buffer.remaining(), len);
                assert read > 0 && read <= buffer.remaining();

                // buffer.get() will do the boundary check for us.
                buffer.get(bytes, off, read);
                return read;
            }

            @Override
            public int read() throws IOException {
                ByteBuffer buffer;
                if ((buffer = current()) == LAST_BUFFER) return -1;
                return buffer.get() & 0xFF;
            }

            @Override
            public void onSubscribe(Flow.Subscription s) {
                if (this.subscription != null) {
                    s.cancel();
                    return;
                }
                this.subscription = s;
                assert buffers.remainingCapacity() > 1; // should at least be 2
                if (DEBUG) err.println("onSubscribe: requesting "
                     + Math.max(1, buffers.remainingCapacity() - 1));
                s.request(Math.max(1, buffers.remainingCapacity() - 1));
            }

            @Override
            public void onNext(List<ByteBuffer> t) {
                try {
                    if (DEBUG) err.println("next item received");
                    if (!buffers.offer(t)) {
                        throw new IllegalStateException("queue is full");
                    }
                    if (DEBUG) err.println("item offered");
                } catch (Exception ex) {
                    failed = ex;
                    try {
                        close();
                    } catch (IOException ex1) {
                        // OK
                    }
                }
            }

            @Override
            public void onError(Throwable thrwbl) {
                subscription = null;
                failed = thrwbl;
            }

            @Override
            public void onComplete() {
                subscription = null;
                onNext(LAST_LIST);
            }

            @Override
            public void close() throws IOException {
                synchronized (this) {
                    if (closed) return;
                    closed = true;
                }
                Flow.Subscription s = subscription;
                subscription = null;
                if (s != null) {
                     s.cancel();
                }
                super.close();
            }

        }
    }

    /**
     * Examine the response headers to figure out the charset used to
     * encode the body content.
     * If the content type is not textual, returns an empty Optional.
     * Otherwise, returns the body content's charset, defaulting to
     * ISO-8859-1 if none is explicitly specified.
     * @param headers The response headers.
     * @return The charset to use for decoding the response body, if
     *         the response body content is text/...
     */
    public static Optional<Charset> getCharset(HttpHeaders headers) {
        Optional<String> contentType = headers.firstValue("Content-Type");
        Optional<Charset> charset = Optional.empty();
        if (contentType.isPresent()) {
            final String[] values = contentType.get().split(";");
            if (values[0].startsWith("text/")) {
                charset = Optional.of(Stream.of(values)
                    .map(x -> x.toLowerCase(Locale.ROOT))
                    .map(String::trim)
                    .filter(x -> x.startsWith("charset="))
                    .map(x -> x.substring("charset=".length()))
                    .findFirst()
                    .orElse("ISO-8859-1"))
                    .map(Charset::forName);
            }
        }
        return charset;
    }

    public static void main(String[] args) throws Exception {
        HttpClient client = HttpClient.newHttpClient();
        HttpRequest request = HttpRequest
            .newBuilder(new URI("https://hg.openjdk.org/jdk9/sandbox/jdk/shortlog/http-client-branch/"))
            .GET()
            .build();

        // This example shows how to return an InputStream that can be used to
        // start reading the response body before the response is fully received.
        // In comparison, the snipet below (which uses
        // HttpResponse.BodyHandlers.ofString()) obviously will not return before the
        // response body is fully read:
        //
        // System.out.println(
        //    client.sendAsync(request, HttpResponse.BodyHandlers.ofString()).get().body());

        CompletableFuture<HttpResponse<InputStream>> handle =
            client.sendAsync(request, new HttpInputStreamHandler(3));
        if (DEBUG) err.println("Request sent");

        HttpResponse<InputStream> pending = handle.get();

        // At this point, the response headers have been received, but the
        // response body may not have arrived yet. This comes from
        // the implementation of HttpResponseInputStream::getBody above,
        // which returns an already completed completion stage, without
        // waiting for any data.
        // We can therefore access the headers - and the body, which
        // is our live InputStream, without waiting...
        HttpHeaders responseHeaders = pending.headers();

        // Get the charset declared in the response headers.
        // The optional will be empty if the content type is not
        // of type text/...
        Optional<Charset> charset = getCharset(responseHeaders);

        try (InputStream is = pending.body();
            // We assume a textual content type. Construct an InputStream
            // Reader with the appropriate Charset.
            // charset.get() will throw NPE if the content is not textual.
            Reader r = new InputStreamReader(is, charset.get())) {

            char[] buff = new char[32];
            int off=0, n=0;
            if (DEBUG) err.println("Start receiving response body");
            if (DEBUG) err.println("Charset: " + charset.get());

            // Start consuming the InputStream as the data arrives.
            // Will block until there is something to read...
            while ((n = r.read(buff, off, buff.length - off)) > 0) {
                assert (buff.length - off) > 0;
                assert n <= (buff.length - off);
                if (n == (buff.length - off)) {
                    System.out.print(buff);
                    off = 0;
                } else {
                    off += n;
                }
                assert off < buff.length;
            }

            // last call to read may not have filled 'buff' completely.
            // flush out the remaining characters.
            assert off >= 0 && off < buff.length;
            for (int i=0; i < off; i++) {
                System.out.print(buff[i]);
            }

            // We're done!
            System.out.println("Done!");
        }
    }

}
