/*
 * 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.internal.websocket;

import jdk.incubator.http.internal.websocket.Frame.Opcode;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.CharacterCodingException;
import java.nio.charset.CharsetEncoder;
import java.nio.charset.CoderResult;
import java.security.SecureRandom;

import static java.nio.charset.StandardCharsets.UTF_8;
import static java.util.Objects.requireNonNull;
import static jdk.incubator.http.internal.common.Utils.EMPTY_BYTEBUFFER;
import static jdk.incubator.http.internal.websocket.Frame.MAX_HEADER_SIZE_BYTES;
import static jdk.incubator.http.internal.websocket.Frame.Opcode.BINARY;
import static jdk.incubator.http.internal.websocket.Frame.Opcode.CLOSE;
import static jdk.incubator.http.internal.websocket.Frame.Opcode.CONTINUATION;
import static jdk.incubator.http.internal.websocket.Frame.Opcode.PING;
import static jdk.incubator.http.internal.websocket.Frame.Opcode.PONG;
import static jdk.incubator.http.internal.websocket.Frame.Opcode.TEXT;

/*
 * A stateful object that represents a WebSocket message being sent to the
 * channel.
 *
 * Data provided to the constructors is copied. Otherwise we would have to deal
 * with mutability, security, masking/unmasking, readonly status, etc. So
 * copying greatly simplifies the implementation.
 *
 * In the case of memory-sensitive environments an alternative implementation
 * could use an internal pool of buffers though at the cost of extra complexity
 * and possible performance degradation.
 */
abstract class OutgoingMessage {

    private static final SecureRandom maskingKeys = new SecureRandom();

    protected ByteBuffer[] frame;
    protected int offset;

    /*
     * Performs contextualization. This method is not a part of the constructor
     * so it would be possible to defer the work it does until the most
     * convenient moment (up to the point where sentTo is invoked).
     */
    protected void contextualize(Context context) {
        if (context.isCloseSent()) {
            throw new IllegalStateException("Close sent");
        }
    }

    protected boolean sendTo(RawChannel channel) throws IOException {
        while ((offset = nextUnwrittenIndex()) != -1) {
            long n = channel.write(frame, offset, frame.length - offset);
            if (n == 0) {
                return false;
            }
        }
        return true;
    }

    private int nextUnwrittenIndex() {
        for (int i = offset; i < frame.length; i++) {
            if (frame[i].hasRemaining()) {
                return i;
            }
        }
        return -1;
    }

    static final class Text extends OutgoingMessage {

        private final ByteBuffer payload;
        private final boolean isLast;

        Text(CharSequence characters, boolean isLast) {
            CharsetEncoder encoder = UTF_8.newEncoder();
            try {
                payload = encoder.encode(CharBuffer.wrap(characters));
            } catch (CharacterCodingException e) {
                throw new IllegalArgumentException(
                        "Malformed UTF-8 text message");
            }
            this.isLast = isLast;
        }

        @Override
        protected void contextualize(Context context) {
            super.contextualize(context);
            if (context.isPreviousBinary() && !context.isPreviousLast()) {
                throw new IllegalStateException("Unexpected text message");
            }
            frame = getDataMessageBuffers(
                    TEXT, context.isPreviousLast(), isLast, payload, payload);
            context.setPreviousBinary(false);
            context.setPreviousText(true);
            context.setPreviousLast(isLast);
        }
    }

    static final class Binary extends OutgoingMessage {

        private final ByteBuffer payload;
        private final boolean isLast;

        Binary(ByteBuffer payload, boolean isLast) {
            this.payload = requireNonNull(payload);
            this.isLast = isLast;
        }

        @Override
        protected void contextualize(Context context) {
            super.contextualize(context);
            if (context.isPreviousText() && !context.isPreviousLast()) {
                throw new IllegalStateException("Unexpected binary message");
            }
            ByteBuffer newBuffer = ByteBuffer.allocate(payload.remaining());
            frame = getDataMessageBuffers(
                    BINARY, context.isPreviousLast(), isLast, payload, newBuffer);
            context.setPreviousText(false);
            context.setPreviousBinary(true);
            context.setPreviousLast(isLast);
        }
    }

    static final class Ping extends OutgoingMessage {

        Ping(ByteBuffer payload) {
            frame = getControlMessageBuffers(PING, payload);
        }
    }

    static final class Pong extends OutgoingMessage {

        Pong(ByteBuffer payload) {
            frame = getControlMessageBuffers(PONG, payload);
        }
    }

    static final class Close extends OutgoingMessage {

        Close() {
            frame = getControlMessageBuffers(CLOSE, EMPTY_BYTEBUFFER);
        }

        Close(int statusCode, CharSequence reason) {
            ByteBuffer payload = ByteBuffer.allocate(125)
                                           .putChar((char) statusCode);
            CoderResult result = UTF_8.newEncoder()
                                      .encode(CharBuffer.wrap(reason),
                                              payload,
                                              true);
            if (result.isOverflow()) {
                throw new IllegalArgumentException("Long reason");
            } else if (result.isError()) {
                try {
                    result.throwException();
                } catch (CharacterCodingException e) {
                    throw new IllegalArgumentException(
                            "Malformed UTF-8 reason", e);
                }
            }
            payload.flip();
            frame = getControlMessageBuffers(CLOSE, payload);
        }

        @Override
        protected void contextualize(Context context) {
            super.contextualize(context);
            context.setCloseSent();
        }
    }

    private static ByteBuffer[] getControlMessageBuffers(Opcode opcode,
                                                         ByteBuffer payload) {
        assert opcode.isControl() : opcode;
        int remaining = payload.remaining();
        if (remaining > 125) {
            throw new IllegalArgumentException
                    ("Long message: " + remaining);
        }
        ByteBuffer frame = ByteBuffer.allocate(MAX_HEADER_SIZE_BYTES + remaining);
        int mask = maskingKeys.nextInt();
        new Frame.HeaderWriter()
                .fin(true)
                .opcode(opcode)
                .payloadLen(remaining)
                .mask(mask)
                .write(frame);
        Frame.Masker.transferMasking(payload, frame, mask);
        frame.flip();
        return new ByteBuffer[]{frame};
    }

    private static ByteBuffer[] getDataMessageBuffers(Opcode type,
                                                      boolean isPreviousLast,
                                                      boolean isLast,
                                                      ByteBuffer payloadSrc,
                                                      ByteBuffer payloadDst) {
        assert !type.isControl() && type != CONTINUATION : type;
        ByteBuffer header = ByteBuffer.allocate(MAX_HEADER_SIZE_BYTES);
        int mask = maskingKeys.nextInt();
        new Frame.HeaderWriter()
                .fin(isLast)
                .opcode(isPreviousLast ? type : CONTINUATION)
                .payloadLen(payloadDst.remaining())
                .mask(mask)
                .write(header);
        header.flip();
        Frame.Masker.transferMasking(payloadSrc, payloadDst, mask);
        payloadDst.flip();
        return new ByteBuffer[]{header, payloadDst};
    }

    /*
     * An instance of this class is passed sequentially between messages, so
     * every message in a sequence can check the context it is in and update it
     * if necessary.
     */
    public static class Context {

        boolean previousLast = true;
        boolean previousBinary;
        boolean previousText;
        boolean closeSent;

        private boolean isPreviousText() {
            return this.previousText;
        }

        private void setPreviousText(boolean value) {
            this.previousText = value;
        }

        private boolean isPreviousBinary() {
            return this.previousBinary;
        }

        private void setPreviousBinary(boolean value) {
            this.previousBinary = value;
        }

        private boolean isPreviousLast() {
            return this.previousLast;
        }

        private void setPreviousLast(boolean value) {
            this.previousLast = value;
        }

        private boolean isCloseSent() {
            return closeSent;
        }

        private void setCloseSent() {
            closeSent = true;
        }
    }
}
