/*
 * Copyright (c) 2015, 2016, 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.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * 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.
 */

package jdk.incubator.http;

import java.io.IOException;
import java.net.ProtocolException;
import java.net.URI;
import java.nio.ByteBuffer;
import java.time.Duration;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;

/**
 * A WebSocket client conforming to RFC&nbsp;6455.
 * {@Incubating}
 *
 * <p> A {@code WebSocket} provides full-duplex communication over a TCP
 * connection.
 *
 * <p> To create a {@code WebSocket} use a {@linkplain HttpClient#newWebSocketBuilder(
 * URI, Listener) builder}. Once a {@code WebSocket} is built, it's ready
 * to send and receive messages. When the {@code WebSocket} is no longer needed
 * it must be closed: a Close message must both be {@linkplain #sendClose()
 * sent} and {@linkplain Listener#onClose(WebSocket, int, String) received}.
 * The {@code WebSocket} may be also closed {@linkplain #abort() abruptly}.
 *
 * <p> Once closed the {@code WebSocket} remains {@linkplain #isClosed() closed}
 * and cannot be reopened.
 *
 * <p> Messages of type {@code X} (where {@code X} is one of: Text, Binary,
 * Ping, Pong or Close) are sent and received asynchronously through the {@code
 * WebSocket.send{X}} and {@link WebSocket.Listener}{@code .on{X}} methods
 * respectively. Each method returns a {@link CompletionStage} which completes
 * when the operation has completed.
 *
 * <p> Note that messages (of any type) are received only if {@linkplain
 * #request(long) requested}.
 *
 * <p> One outstanding send operation is permitted. No further send operation
 * can be initiated before the previous one has completed. When sending, a
 * message must not be modified until the returned {@link CompletableFuture}
 * completes (either normally or exceptionally).
 *
 * <p> Text and Binary messages can be sent and received as a whole or in parts.
 * A whole message is transferred as a sequence of one or more invocations of a
 * corresponding method where the last invocation is identified via an
 * additional method argument.
 *
 * <p> If the message is contained in a {@link ByteBuffer}, bytes are considered
 * arranged from the {@code buffer}'s {@link ByteBuffer#position() position} to
 * the {@code buffer}'s {@link ByteBuffer#limit() limit}.
 *
 * <p> Unless otherwise stated, {@code null} parameter values will cause methods
 * and constructors to throw {@link NullPointerException}.
 *
 * @implNote This implementation's methods do not block before returning
 * a {@code CompletableFuture}.
 *
 * @since 9
 */
public interface WebSocket {

    /**
     * The WebSocket Close message status code (<code>{@value}</code>),
     * indicating normal closure, meaning that the purpose for which the
     * connection was established has been fulfilled.
     *
     * @see #sendClose(int, String)
     * @see Listener#onClose(WebSocket, int, String)
     */
    int NORMAL_CLOSURE = 1000;

    /**
     * The WebSocket Close message status code (<code>{@value}</code>), is
     * designated for use in applications expecting a status code to indicate
     * that the connection was closed abnormally, e.g., without sending or
     * receiving a Close message.
     *
     * @see Listener#onClose(WebSocket, int, String)
     * @see #abort()
     */
    int CLOSED_ABNORMALLY = 1006;

    /**
     * A builder for creating {@code WebSocket} instances.
     * {@Incubating}
     *
     * <p> To build a {@code WebSocket}, {@linkplain HttpClient#newWebSocketBuilder(
     * URI, Listener) create} a builder, configure it as required by
     * calling intermediate methods (the ones that return the builder itself),
     * then finally call {@link #buildAsync()} to get a {@link
     * CompletableFuture} with resulting {@code WebSocket}.
     *
     * <p> If an intermediate method has not been called, an appropriate
     * default value (or behavior) will be used. Unless otherwise noted, a
     * repeated call to an intermediate method overwrites the previous value (or
     * overrides the previous behaviour).
     *
     * <p> Instances of {@code Builder} are not safe for use by multiple threads
     * without external synchronization.
     *
     * @since 9
     */
    interface Builder {

        /**
         * Adds the given name-value pair to the list of additional headers for
         * the opening handshake.
         *
         * <p> Headers defined in WebSocket Protocol are not allowed to be added.
         *
         * @param name
         *         the header name
         * @param value
         *         the header value
         *
         * @return this builder
         */
        Builder header(String name, String value);

        /**
         * Includes a request for the given subprotocols during the opening
         * handshake.
         *
         * <p> Among the requested subprotocols at most one will be chosen by
         * the server. This subprotocol will be available from {@link
         * WebSocket#getSubprotocol}. Subprotocols are specified in the order of
         * preference.
         *
         * <p> Each of the given subprotocols must conform to the relevant
         * rules defined in the WebSocket Protocol.
         *
         * <p> If this method is not invoked then no subprotocols are requested.
         *
         * @param mostPreferred
         *         the most preferred subprotocol
         * @param lesserPreferred
         *         the lesser preferred subprotocols, with the least preferred
         *         at the end
         *
         * @return this builder
         */
        Builder subprotocols(String mostPreferred, String... lesserPreferred);

        /**
         * Sets a timeout for the opening handshake.
         *
         * <p> If the opening handshake does not complete within the specified
         * duration then the {@code CompletableFuture} returned from {@link
         * #buildAsync()} completes exceptionally with a {@link
         * HttpTimeoutException}.
         *
         * <p> If this method is not invoked then the timeout is deemed infinite.
         *
         * @param timeout
         *         the timeout, non-{@linkplain Duration#isNegative() negative},
         *         non-{@linkplain Duration#ZERO ZERO}
         *
         * @return this builder
         */
        Builder connectTimeout(Duration timeout);

        /**
         * Builds a {@code WebSocket}.
         *
         * <p> Returns a {@code CompletableFuture<WebSocket>} which completes
         * normally with the {@code WebSocket} when it is connected or completes
         * exceptionally if an error occurs.
         *
         * <p> {@code CompletableFuture} may complete exceptionally with the
         * following errors:
         * <ul>
         * <li> {@link IOException} -
         *          if an I/O error occurs
         * <li> {@link WebSocketHandshakeException} -
         *          if the opening handshake fails
         * <li> {@link HttpTimeoutException} -
         *          if the opening handshake does not complete within
         *          the specified {@linkplain #connectTimeout(Duration) duration}
         * <li> {@link InterruptedException} -
         *          if the operation was interrupted
         * <li> {@link SecurityException} -
         *          if a security manager is set, and the caller does not
         *          have a {@link java.net.URLPermission} for the WebSocket URI
         * <li> {@link IllegalArgumentException} -
         *          if any of the additional {@link #header(String, String)
         *          headers} are illegal;
         *          or if any of the WebSocket Protocol rules relevant to {@link
         *          #subprotocols(String, String...) subprotocols} are violated;
         *          or if the {@link #connectTimeout(Duration) connect timeout}
         *          is invalid;
         * </ul>
         *
         * @return a {@code CompletableFuture} with the {@code WebSocket}
         */
        CompletableFuture<WebSocket> buildAsync();
    }

    /**
     * A listener for events and messages on a {@code WebSocket}.
     * {@Incubating}
     *
     * <p> Each method of {@code Listener} corresponds to a type of event or a
     * type of message. The {@code WebSocket} argument of the method is the
     * {@code WebSocket} the event has occurred (the message has been received)
     * on. All methods with the same {@code WebSocket} argument are invoked in a
     * sequential
     * (and <a href="../../../java/util/concurrent/package-summary.html#MemoryVisibility">happens-before</a>)
     * order, one after another, possibly by different threads.
     *
     * <ul>
     * <li> {@link #onOpen(WebSocket) onOpen} <br>
     * This method is invoked first.
     * <li> {@link #onText(WebSocket, CharSequence, WebSocket.MessagePart)
     * onText}, {@link #onBinary(WebSocket, ByteBuffer, WebSocket.MessagePart)
     * onBinary}, {@link #onPing(WebSocket, ByteBuffer) onPing} and {@link
     * #onPong(WebSocket, ByteBuffer) onPong} <br>
     * These methods are invoked zero or more times after {@code onOpen}.
     * <li> {@link #onClose(WebSocket, int, String) onClose}, {@link
     * #onError(WebSocket, Throwable) onError} <br>
     * Only one of these methods is invoked, and that method is invoked last.
     * </ul>
     *
     * <p> Messages received by the {@code Listener} conform to the WebSocket
     * Protocol, otherwise {@code onError} with a {@link ProtocolException} is
     * invoked.
     *
     * <p> If a whole message is received, then the corresponding method
     * ({@code onText} or {@code onBinary}) will be invoked with {@link
     * WebSocket.MessagePart#WHOLE WHOLE} marker. Otherwise the method will be
     * invoked with {@link WebSocket.MessagePart#FIRST FIRST}, zero or more
     * times with {@link WebSocket.MessagePart#PART PART} and, finally, with
     * {@link WebSocket.MessagePart#LAST LAST} markers.
     *
     * If any of the methods above throws an exception, {@code onError} is then
     * invoked with the same {@code WebSocket} and this exception. Exceptions
     * thrown from {@code onError} or {@code onClose} are ignored.
     *
     * <p> When the method returns, the message is deemed received (in
     * particular, if contained in a {@code ByteBuffer buffer}, the data is
     * deemed received completely regardless of the result {@code
     * buffer.hasRemaining()} upon the method's return. After this further
     * messages may be received.
     *
     * <p> These invocations begin asynchronous processing which might not end
     * with the invocation. To provide coordination, methods of {@code Listener}
     * return a {@link CompletionStage CompletionStage}.
     * The {@code CompletionStage} signals the {@code WebSocket} that the
     * processing of a message has ended. For convenience, methods may return
     * {@code null}, which (by convention) means the same as returning an
     * already completed (normally) {@code CompletionStage}.
     * If the returned {@code CompletionStage} completes exceptionally, then
     * {@link #onError(WebSocket, Throwable) onError} will be invoked with the
     * same {@code WebSocket} and this exception.
     *
     * <p> Control of the message passes to the {@code Listener} with the
     * invocation of the method. Control of the message returns to the {@code
     * WebSocket} at the earliest of, either returning {@code null} from the
     * method, or the completion of the {@code CompletionStage} returned from
     * the method. The {@code WebSocket} does not access the message while it's
     * not in its control. The {@code Listener} must not access the message
     * after its control has been returned to the {@code WebSocket}.
     *
     * <p> A {@code WebSocket} implementation never invokes {@code Listener}'s
     * methods with {@code null}s as their arguments.
     *
     * @since 9
     */
    interface Listener {

        /**
         * Notifies the {@code Listener} that it is connected to the provided
         * {@code WebSocket}.
         *
         * <p> The {@code onOpen} method does not correspond to any message from
         * the WebSocket Protocol. It is a synthetic event and the first {@code
         * Listener}'s method to be invoked.
         *
         * <p> This method is usually used to make an initial {@linkplain
         * WebSocket#request(long) request} for messages.
         *
         * <p> If an exception is thrown from this method then {@link
         * #onError(WebSocket, Throwable) onError} will be invoked with the same
         * {@code WebSocket} and this exception.
         *
         * @implSpec The default implementation of this method behaves as if:
         *
         * <pre>{@code
         *     webSocket.request(1);
         * }</pre>
         *
         * @param webSocket
         *         the WebSocket
         */
        default void onOpen(WebSocket webSocket) { webSocket.request(1); }

        /**
         * Receives a Text message.
         *
         * <p> The {@code onText} method is invoked zero or more times between
         * {@code onOpen} and ({@code onClose} or {@code onError}).
         *
         * <p> This message may be a partial UTF-16 sequence. However, the
         * concatenation of all messages through the last will be a whole UTF-16
         * sequence.
         *
         * <p> If an exception is thrown from this method or the returned {@code
         * CompletionStage} completes exceptionally, then {@link
         * #onError(WebSocket, Throwable) onError} will be invoked with the same
         * {@code WebSocket} and this exception.
         *
         * @implSpec The default implementation of this method behaves as if:
         *
         * <pre>{@code
         *     webSocket.request(1);
         *     return null;
         * }</pre>
         *
         * @implNote This implementation passes only complete UTF-16 sequences
         * to the {@code onText} method.
         *
         * @param webSocket
         *         the WebSocket
         * @param message
         *         the message
         * @param part
         *         the part
         *
         * @return a {@code CompletionStage} which completes when the message
         * processing is done; or {@code null} if already done
         */
        default CompletionStage<?> onText(WebSocket webSocket,
                                          CharSequence message,
                                          MessagePart part) {
            webSocket.request(1);
            return null;
        }

        /**
         * Receives a Binary message.
         *
         * <p> The {@code onBinary} method is invoked zero or more times
         * between {@code onOpen} and ({@code onClose} or {@code onError}).
         *
         * <p> If an exception is thrown from this method or the returned {@code
         * CompletionStage} completes exceptionally, then {@link
         * #onError(WebSocket, Throwable) onError} will be invoked with the same
         * {@code WebSocket} and this exception.
         *
         * @implSpec The default implementation of this method behaves as if:
         *
         * <pre>{@code
         *     webSocket.request(1);
         *     return null;
         * }</pre>
         *
         * @param webSocket
         *         the WebSocket
         * @param message
         *         the message
         * @param part
         *         the part
         *
         * @return a {@code CompletionStage} which completes when the message
         * processing is done; or {@code null} if already done
         */
        default CompletionStage<?> onBinary(WebSocket webSocket,
                                            ByteBuffer message,
                                            MessagePart part) {
            webSocket.request(1);
            return null;
        }

        /**
         * Receives a Ping message.
         *
         * <p> A Ping message may be sent or received by either client or
         * server. It may serve either as a keepalive or as a means to verify
         * that the remote endpoint is still responsive.
         *
         * <p> The {@code WebSocket} handles Ping messages by replying with
         * appropriate Pong messages using a strategy of its choice, but within
         * the boundaries of the WebSocket Protocol. The {@code WebSocket} may
         * invoke {@code onPing} after handling a Ping message, before doing so
         * or in parallel with it. In other words no particular ordering is
         * guaranteed. If an error occurs while implementation handles this Ping
         * message, then {@code onError} will be invoked with this error. For
         * more details on handling Ping messages see RFC 6455 sections
         * <a href="https://tools.ietf.org/html/rfc6455#section-5.5.2">5.5.2. Ping</a>
         * and
         * <a href="https://tools.ietf.org/html/rfc6455#section-5.5.3">5.5.3. Pong</a>.
         *
         * <p> The message will consist of not more than {@code 125} bytes:
         * {@code message.remaining() <= 125}.
         *
         * <p> The {@code onPing} is invoked zero or more times in between
         * {@code onOpen} and ({@code onClose} or {@code onError}).
         *
         * <p> If an exception is thrown from this method or the returned {@code
         * CompletionStage} completes exceptionally, then {@link
         * #onError(WebSocket, Throwable) onError} will be invoked with this
         * exception.
         *
         * @implSpec The default implementation of this method behaves as if:
         *
         * <pre>{@code
         *     webSocket.request(1);
         *     return null;
         * }</pre>
         *
         * @param webSocket
         *         the WebSocket
         * @param message
         *         the message
         *
         * @return a {@code CompletionStage} which completes when the message
         * processing is done; or {@code null} if already done
         */
        default CompletionStage<?> onPing(WebSocket webSocket,
                                          ByteBuffer message) {
            webSocket.request(1);
            return null;
        }

        /**
         * Receives a Pong message.
         *
         * <p> A Pong message may be unsolicited or may be received in response
         * to a previously sent Ping. In the latter case, the contents of the
         * Pong is identical to the originating Ping.
         *
         * <p> The message will consist of not more than {@code 125} bytes:
         * {@code message.remaining() <= 125}.
         *
         * <p> The {@code onPong} method is invoked zero or more times in
         * between {@code onOpen} and ({@code onClose} or {@code onError}).
         *
         * <p> If an exception is thrown from this method or the returned {@code
         * CompletionStage} completes exceptionally, then {@link
         * #onError(WebSocket, Throwable) onError} will be invoked with this
         * exception.
         *
         * @implSpec The default implementation of this method behaves as if:
         *
         * <pre>{@code
         *     webSocket.request(1);
         *     return null;
         * }</pre>
         *
         * @param webSocket
         *         the WebSocket
         * @param message
         *         the message
         *
         * @return a {@code CompletionStage} which completes when the message
         * processing is done; or {@code null} if already done
         */
        default CompletionStage<?> onPong(WebSocket webSocket,
                                          ByteBuffer message) {
            webSocket.request(1);
            return null;
        }

        /**
         * Receives a Close message.
         *
         * <p> A Close message consists of a status code and a reason for
         * closing. The status code is an integer in the range {@code 1000 <=
         * code <= 65535}. The {@code reason} is a short string that has an
         * UTF-8 representation not longer than {@code 123} bytes. For more
         * details on Close message, status codes and reason see RFC 6455 sections
         * <a href="https://tools.ietf.org/html/rfc6455#section-5.5.1">5.5.1. Close</a>
         * and
         * <a href="https://tools.ietf.org/html/rfc6455#section-7.4">7.4. Status Codes</a>.
         *
         * <p> After the returned {@code CompletionStage} has completed
         * (normally or exceptionally), the {@code WebSocket} completes the
         * closing handshake by replying with an appropriate Close message.
         *
         * <p> This implementation replies with a Close message that has the
         * same code this message has and an empty reason.
         *
         * <p> {@code onClose} is the last invocation on the {@code Listener}.
         * It is invoked at most once, but after {@code onOpen}. If an exception
         * is thrown from this method, it is ignored.
         *
         * <p> The {@code WebSocket} will close at the earliest of completion of
         * the returned {@code CompletionStage} or sending a Close message. In
         * particular, if a Close message has been {@link WebSocket#sendClose()
         * sent} before, then this invocation completes the closing handshake
         * and by the time this method is invoked, the {@code WebSocket} will
         * have been closed.
         *
         * @implSpec The default implementation of this method behaves as if:
         *
         * <pre>{@code
         *     return null;
         * }</pre>
         *
         * @param webSocket
         *         the WebSocket
         * @param statusCode
         *         the status code
         * @param reason
         *         the reason
         *
         * @return a {@code CompletionStage} which completes when the {@code
         * WebSocket} can be closed; or {@code null} if it can be closed immediately
         *
         * @see #NORMAL_CLOSURE
         */
        default CompletionStage<?> onClose(WebSocket webSocket,
                                           int statusCode,
                                           String reason) {
            return null;
        }

        /**
         * Notifies an I/O or protocol error has occurred.
         *
         * <p> The {@code onError} method does not correspond to any message
         * from the WebSocket Protocol. It is a synthetic event and the last
         * {@code Listener}'s method to be invoked. It is invoked at most once
         * but after {@code onOpen}. If an exception is thrown from this method,
         * it is ignored.
         *
         * <p> Note that the WebSocket Protocol requires <i>some</i> errors
         * occur in the incoming destination must be fatal to the connection. In
         * such cases the implementation takes care of <i>Failing the WebSocket
         * Connection</i>: by the time {@code onError} is invoked, the {@code
         * WebSocket} will have been closed. Any outstanding or subsequent send
         * operation will complete exceptionally with an {@code IOException}.
         * For more details on Failing the WebSocket Connection see RFC 6455
         * section <a href="https://tools.ietf.org/html/rfc6455#section-7.1.7">7.1.7. Fail the WebSocket Connection</a>.
         *
         * @apiNote Errors associated with sending messages are reported to the
         * {@code CompletableFuture}s {@code sendX} methods return, rather than
         * to this this method.
         *
         * @implSpec The default implementation of this method does nothing.
         *
         * @param webSocket
         *         the WebSocket
         * @param error
         *         the error
         */
        default void onError(WebSocket webSocket, Throwable error) { }
    }

    /**
     * A marker used by {@link WebSocket.Listener} in cases where a partial
     * message may be received.
     * {@Incubating}
     *
     * @see Listener#onText(WebSocket, CharSequence, MessagePart)
     * @see Listener#onBinary(WebSocket, ByteBuffer, MessagePart)
     *
     * @since 9
     */
    enum MessagePart {

        /**
         * The first part of a message in a sequence.
         */
        FIRST,

        /**
         * A middle part of a message in a sequence.
         */
        PART,

        /**
         * The last part of a message in a sequence.
         */
        LAST,

        /**
         * A whole message consisting of a single part.
         */
        WHOLE
    }

    /**
     * Sends a Text message with characters from the given {@code CharSequence}.
     *
     * <p> Returns a {@code CompletableFuture<WebSocket>} which completes
     * normally when the message has been sent or completes exceptionally if an
     * error occurs.
     *
     * <p> The {@code CharSequence} must not be modified until the returned
     * {@code CompletableFuture} completes (either normally or exceptionally).
     *
     * <p> The returned {@code CompletableFuture} can complete exceptionally
     * with:
     * <ul>
     * <li> {@link IllegalArgumentException} -
     *          if {@code message} is a malformed UTF-16 sequence
     * <li> {@link IllegalStateException} -
     *          if the {@code WebSocket} is closed;
     *          or if a Close message has been sent;
     *          or if there is an outstanding send operation;
     *          or if a previous Binary message was sent with {@code isLast == false}
     * <li> {@link IOException} -
     *          if an I/O error occurs during this operation;
     *          or if the {@code WebSocket} has been closed due to an error;
     * </ul>
     *
     * @implNote This implementation does not accept partial UTF-16 sequences.
     * In case such a sequence is passed, a returned {@code CompletableFuture}
     * completes exceptionally with {@code IOException}.
     *
     * @param message
     *         the message
     * @param isLast
     *         {@code true} if this is the last part of the message,
     *         {@code false} otherwise
     *
     * @return a {@code CompletableFuture} with this {@code WebSocket}
     */
    CompletableFuture<WebSocket> sendText(CharSequence message, boolean isLast);

    /**
     * Sends a whole Text message with characters from the given {@code
     * CharSequence}.
     *
     * <p> This is a convenience method. For the general case, use {@link
     * #sendText(CharSequence, boolean)}.
     *
     * <p> Returns a {@code CompletableFuture<WebSocket>} which completes
     * normally when the message has been sent or completes exceptionally if an
     * error occurs.
     *
     * <p> The {@code CharSequence} must not be modified until the returned
     * {@code CompletableFuture} completes (either normally or exceptionally).
     *
     * <p> The returned {@code CompletableFuture} can complete exceptionally
     * with:
     * <ul>
     * <li> {@link IllegalArgumentException} -
     *          if {@code message} is a malformed UTF-16 sequence
     * <li> {@link IllegalStateException} -
     *          if the {@code WebSocket} is closed;
     *          or if a Close message has been sent;
     *          or if there is an outstanding send operation;
     *          or if a previous Binary message was sent with {@code isLast == false}
     * <li> {@link IOException} -
     *          if an I/O error occurs during this operation;
     *          or if the {@code WebSocket} has been closed due to an error;
     * </ul>
     *
     * @param message
     *         the message
     *
     * @return a {@code CompletableFuture} with this {@code WebSocket}
     */
    default CompletableFuture<WebSocket> sendText(CharSequence message) {
        return sendText(message, true);
    }

    /**
     * Sends a Binary message with bytes from the given {@code ByteBuffer}.
     *
     * <p> Returns a {@code CompletableFuture<WebSocket>} which completes
     * normally when the message has been sent or completes exceptionally if an
     * error occurs.
     *
     * <p> The returned {@code CompletableFuture} can complete exceptionally
     * with:
     * <ul>
     * <li> {@link IllegalStateException} -
     *          if the {@code WebSocket} is closed;
     *          or if a Close message has been sent;
     *          or if there is an outstanding send operation;
     *          or if a previous Text message was sent with {@code isLast == false}
     * <li> {@link IOException} -
     *          if an I/O error occurs during this operation;
     *          or if the {@code WebSocket} has been closed due to an error
     * </ul>
     *
     * @param message
     *         the message
     * @param isLast
     *         {@code true} if this is the last part of the message,
     *         {@code false} otherwise
     *
     * @return a {@code CompletableFuture} with this {@code WebSocket}
     */
    CompletableFuture<WebSocket> sendBinary(ByteBuffer message, boolean isLast);

    /**
     * Sends a Ping message with bytes from the given ByteBuffer.
     *
     * <p> Returns a {@code CompletableFuture<WebSocket>} which completes
     * normally when the message has been sent or completes exceptionally if an
     * error occurs.
     *
     * <p> A Ping message may be sent or received by either client or server.
     * It may serve either as a keepalive or as a means to verify that the
     * remote endpoint is still responsive.
     *
     * <p> The message must consist of not more than {@code 125} bytes: {@code
     * message.remaining() <= 125}.
     *
     * <p> The returned {@code CompletableFuture} can complete exceptionally
     * with:
     * <ul>
     * <li> {@link IllegalArgumentException} -
     *          if {@code message.remaining() > 125}
     * <li> {@link IllegalStateException} -
     *          if the {@code WebSocket} is closed;
     *          or if a Close message has been sent;
     *          or if there is an outstanding send operation
     * <li> {@link IOException} -
     *          if an I/O error occurs during this operation;
     *          or if the {@code WebSocket} has been closed due to an error
     * </ul>
     *
     * @param message
     *         the message
     *
     * @return a {@code CompletableFuture} with this {@code WebSocket}
     */
    CompletableFuture<WebSocket> sendPing(ByteBuffer message);

    /**
     * Sends a Pong message with bytes from the given ByteBuffer.
     *
     * <p> Returns a {@code CompletableFuture<WebSocket>} which completes
     * normally when the message has been sent or completes exceptionally if an
     * error occurs.
     *
     * <p> A Pong message may be unsolicited or may be sent in response to a
     * previously received Ping. In latter case the contents of the Pong must be
     * identical to the originating Ping.
     *
     * <p> The message must consist of not more than {@code 125} bytes: {@code
     * message.remaining() <= 125}.
     *
     * <p> The returned {@code CompletableFuture} can complete exceptionally
     * with:
     * <ul>
     * <li> {@link IllegalArgumentException} -
     *          if {@code message.remaining() > 125}
     * <li> {@link IllegalStateException} -
     *          if the {@code WebSocket} is closed;
     *          or if a Close message has been sent;
     *          or if there is an outstanding send operation
     * <li> {@link IOException} -
     *          if an I/O error occurs during this operation;
     *          or if the {@code WebSocket} has been closed due to an error
     * </ul>
     *
     * @param message
     *         the message
     *
     * @return a {@code CompletableFuture} with this {@code WebSocket}
     */
    CompletableFuture<WebSocket> sendPong(ByteBuffer message);

    /**
     * Sends a Close message with the given status code and the reason.
     *
     * <p> When this method has been invoked, no further messages can be sent.
     *
     * <p> The {@code statusCode} is an integer in the range {@code 1000 <= code
     * <= 4999}. However, not all status codes may be legal in some
     * implementations. Regardless of an implementation,
     * <code>{@value jdk.incubator.http.WebSocket#NORMAL_CLOSURE}</code>
     * is always legal and {@code 1002}, {@code 1003}, {@code 1005}, {@code
     * 1006}, {@code 1007}, {@code 1009}, {@code 1010}, {@code 1012}, {@code
     * 1013} and {@code 1015} are always illegal codes.
     *
     * <p> The {@code reason} is a short string that must have an UTF-8
     * representation not longer than {@code 123} bytes. For more details on
     * Close message, status codes and reason see RFC 6455 sections
     * <a href="https://tools.ietf.org/html/rfc6455#section-5.5.1">5.5.1. Close</a>
     * and
     * <a href="https://tools.ietf.org/html/rfc6455#section-7.4">7.4. Status Codes</a>.
     *
     * <p> The method returns a {@code CompletableFuture<WebSocket>} which
     * completes normally when the message has been sent or completes
     * exceptionally if an error occurs.
     *
     * <p> The returned {@code CompletableFuture} can complete exceptionally
     * with:
     * <ul>
     * <li> {@link IllegalArgumentException} -
     *          if the {@code statusCode} has an illegal value;
     *          or if {@code reason} doesn't have an UTF-8 representation of
     *          length {@code <= 123}
     * <li> {@link IOException} -
     *          if an I/O error occurs during this operation;
     *          or the {@code WebSocket} has been closed due to an error
     * </ul>
     *
     * <p> If this method has already been invoked or the {@code WebSocket} is
     * closed, then subsequent invocations of this method have no effect and the
     * returned {@code CompletableFuture} completes normally.
     *
     * <p> If a Close message has been {@linkplain Listener#onClose(WebSocket,
     * int, String) received} before, then this invocation completes the closing
     * handshake and by the time the returned {@code CompletableFuture}
     * completes, the {@code WebSocket} will have been closed.
     *
     * @param statusCode
     *         the status code
     * @param reason
     *         the reason
     *
     * @return a {@code CompletableFuture} with this {@code WebSocket}
     *
     * @see #sendClose()
     */
    CompletableFuture<WebSocket> sendClose(int statusCode, String reason);

    /**
     * Sends an empty Close message.
     *
     * <p> When this method has been invoked, no further messages can be sent.
     *
     * <p> For more details on Close message see RFC 6455 section
     * <a href="https://tools.ietf.org/html/rfc6455#section-5.5.1">5.5.1. Close</a>
     *
     * <p> The method returns a {@code CompletableFuture<WebSocket>} which
     * completes normally when the message has been sent or completes
     * exceptionally if an error occurs.
     *
     * <p> The returned {@code CompletableFuture} can complete exceptionally
     * with:
     * <ul>
     * <li> {@link IOException} -
     *          if an I/O error occurs during this operation;
     *          or the {@code WebSocket} has been closed due to an error
     * </ul>
     *
     * <p> If this method has already been invoked or the {@code WebSocket} is
     * closed, then subsequent invocations of this method have no effect and the
     * returned {@code CompletableFuture} completes normally.
     *
     * <p> If a Close message has been {@linkplain Listener#onClose(WebSocket,
     * int, String) received} before, then this invocation completes the closing
     * handshake and by the time the returned {@code CompletableFuture}
     * completes, the {@code WebSocket} will have been closed.
     *
     * @return a {@code CompletableFuture} with this {@code WebSocket}
     *
     * @see #sendClose(int, String)
     */
    CompletableFuture<WebSocket> sendClose();

    /**
     * Allows {@code n} more messages to be received by the {@link Listener
     * Listener}.
     *
     * <p> The actual number of received messages might be fewer if a Close
     * message is received, the {@code WebSocket} closes or an error occurs.
     *
     * <p> A {@code WebSocket} that has just been built, hasn't requested
     * anything yet. Usually the initial request for messages is made in {@link
     * Listener#onOpen(jdk.incubator.http.WebSocket) Listener.onOpen}.
     *
     * <p> If the {@code WebSocket} is closed then invoking this method has no
     * effect.
     *
     * @implNote This implementation does not distinguish between partial and
     * whole messages, because it's not known beforehand how a message will be
     * received.
     *
     * <p> If a server sends more messages than requested, this implementation
     * queues up these messages on the TCP connection and may eventually force
     * the sender to stop sending through TCP flow control.
     *
     * @param n
     *         the number of messages
     *
     * @throws IllegalArgumentException
     *         if {@code n < 0}
     */
    void request(long n);

    /**
     * Returns a {@linkplain Builder#subprotocols(String, String...) subprotocol}
     * which has been chosen for this {@code WebSocket}.
     *
     * @return a subprotocol, or an empty {@code String} if there is none
     */
    String getSubprotocol();

    /**
     * Tells whether the {@code WebSocket} is closed.
     *
     * <p> When a {@code WebSocket} is closed no further messages can be sent or
     * received.
     *
     * @return {@code true} if the {@code WebSocket} is closed,
     *         {@code false} otherwise
     */
    boolean isClosed();

    /**
     * Closes the {@code WebSocket} abruptly.
     *
     * <p> This method may be invoked at any time. This method closes the
     * underlying TCP connection and puts the {@code WebSocket} into a closed
     * state.
     *
     * <p> As the result {@link Listener#onClose(WebSocket, int, String)
     * Listener.onClose} will be invoked with the status code {@link
     * #CLOSED_ABNORMALLY} unless either {@code onClose} or {@link
     * Listener#onError(WebSocket, Throwable) onError} has been invoked before.
     * In which case no additional invocation will happen.
     *
     * <p> If the {@code WebSocket} is already closed then invoking this method
     * has no effect.
     *
     * @throws IOException
     *         if an I/O error occurs
     */
    void abort() throws IOException;
}
