//
//  ========================================================================
//  Copyright (c) 1995-2017 Mort Bay Consulting Pty. Ltd.
//  ------------------------------------------------------------------------
//  All rights reserved. This program and the accompanying materials
//  are made available under the terms of the Eclipse Public License v1.0
//  and Apache License v2.0 which accompanies this distribution.
//
//      The Eclipse Public License is available at
//      http://www.eclipse.org/legal/epl-v10.html
//
//      The Apache License v2.0 is available at
//      http://www.opensource.org/licenses/apache2.0.php
//
//  You may elect to redistribute this code under either of these licenses.
//  ========================================================================
//

package org.eclipse.jetty.websocket.jsr356;

import static org.hamcrest.Matchers.instanceOf;

import java.io.IOException;
import java.net.URI;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;

import javax.websocket.ContainerProvider;
import javax.websocket.Endpoint;
import javax.websocket.EndpointConfig;
import javax.websocket.MessageHandler;
import javax.websocket.Session;
import javax.websocket.WebSocketContainer;

import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Test;

/**
 * This class tests receiving of messages by different types of {@link MessageHandler}
 */
public class MessageReceivingTest {
    private static final Logger LOG = Log.getLogger(EndpointEchoTest.class);
    private static Server server;
    private static EchoHandler handler;
    private static URI serverUri;
    private WebSocketContainer container;
    private final String VERY_LONG_STRING;

    public MessageReceivingTest() {
        byte raw[] = new byte[1024 * 1024];
        Arrays.fill(raw, (byte)'x');
        VERY_LONG_STRING = new String(raw, StandardCharsets.UTF_8);
    }

    @BeforeClass
    public static void startServer() throws Exception {
        server = new Server();
        ServerConnector connector = new ServerConnector(server);
        server.addConnector(connector);

        handler = new EchoHandler();

        ContextHandler context = new ContextHandler();
        context.setContextPath("/");
        context.setHandler(handler);
        server.setHandler(context);

        // Start Server
        server.start();

        String host = connector.getHost();
        if (host == null) {
            host = "localhost";
        }
        int port = connector.getLocalPort();
        serverUri = new URI(String.format("ws://%s:%d/", host, port));
    }

    @AfterClass
    public static void stopServer() {
        try {
            server.stop();
        } catch (Exception e) {
            e.printStackTrace(System.err);
        }
    }

    @Before
    public void configureTest() {
        container = ContainerProvider.getWebSocketContainer();
    }

    /**
     * Method tests receiving of text messages at once.
     *
     * @throws Exception on exception occur
     */
    @Test
    @Ignore("flappy test")
    public void testWholeTextMessage() throws Exception {
        final TestEndpoint echoer = new TestEndpoint(new WholeStringCaptureHandler());
        Assert.assertThat(echoer, instanceOf(javax.websocket.Endpoint.class));
        // Issue connect using instance of class that extends Endpoint
        final Session session = container.connectToServer(echoer, serverUri);
        if (LOG.isDebugEnabled())
            LOG.debug("Client Connected: {}", session);
        session.getBasicRemote().sendText("");
        session.getBasicRemote().sendText("Echo");
        session.getBasicRemote().sendText(VERY_LONG_STRING);
        session.getBasicRemote().sendText("Echo");
        if (LOG.isDebugEnabled())
            LOG.debug("Client Message Sent");
        echoer.handler.getMessageQueue().awaitMessages(2, 1000, TimeUnit.MILLISECONDS);
    }

    /**
     * Method tests receiving of text messages by parts.
     *
     * @throws Exception on exception occur
     */
    @Test
    public void testPartialTextMessage() throws Exception {
        final TestEndpoint echoer = new TestEndpoint(new PartialStringCaptureHandler());
        Assert.assertThat(echoer, instanceOf(javax.websocket.Endpoint.class));
        // Issue connect using instance of class that extends Endpoint
        final Session session = container.connectToServer(echoer, serverUri);
        if (LOG.isDebugEnabled())
            LOG.debug("Client Connected: {}", session);
        session.getBasicRemote().sendText("");
        session.getBasicRemote().sendText("Echo");
        if (LOG.isDebugEnabled())
            LOG.debug("Client Message Sent");
        echoer.handler.getMessageQueue().awaitMessages(2, 1000, TimeUnit.MILLISECONDS);
    }

    /**
     * Method tests receiving of binary messages at once.
     *
     * @throws Exception on exception occur
     */
    @Test
    public void testWholeBinaryMessage() throws Exception {
        final TestEndpoint echoer = new TestEndpoint(new WholeByteBufferCaptureHandler());
        Assert.assertThat(echoer, instanceOf(javax.websocket.Endpoint.class));
        // Issue connect using instance of class that extends Endpoint
        final Session session = container.connectToServer(echoer, serverUri);
        if (LOG.isDebugEnabled())
            LOG.debug("Client Connected: {}", session);
        sendBinary(session, "");
        sendBinary(session, "Echo");
        if (LOG.isDebugEnabled())
            LOG.debug("Client Message Sent");
        echoer.handler.getMessageQueue().awaitMessages(2, 1000, TimeUnit.MILLISECONDS);
    }

    /**
     * Method tests receiving of binary messages by parts.
     *
     * @throws Exception on exception occur
     */
    @Test
    public void testPartialBinaryMessage() throws Exception {
        final TestEndpoint echoer = new TestEndpoint(new PartialByteBufferCaptureHandler());
        Assert.assertThat(echoer, instanceOf(javax.websocket.Endpoint.class));
        // Issue connect using instance of class that extends Endpoint
        final Session session = container.connectToServer(echoer, serverUri);
        if (LOG.isDebugEnabled())
            LOG.debug("Client Connected: {}", session);
        sendBinary(session, "");
        sendBinary(session, "Echo");
        if (LOG.isDebugEnabled())
            LOG.debug("Client Message Sent");
        echoer.handler.getMessageQueue().awaitMessages(2, 1000, TimeUnit.MILLISECONDS);
    }

    private static void sendBinary(Session session, String message) throws IOException {
        final ByteBuffer bb = ByteBuffer.wrap(message.getBytes());
        session.getBasicRemote().sendBinary(bb);
    }

    private static class TestEndpoint extends Endpoint {
        public final AbstractHandler handler;

        public TestEndpoint(AbstractHandler handler) {
            this.handler = handler;
        }

        @Override
        public void onOpen(Session session, EndpointConfig config) {
            session.addMessageHandler(handler);
        }

    }

    /**
     * Abstract message handler implementation, used for tests.
     */
    private static abstract class AbstractHandler implements MessageHandler {
        /**
         * Message queue to put the result messages.
         */
        private final MessageQueue messageQueue = new MessageQueue();

        /**
         * Returns message queue to test received messages count.
         *
         * @return message queue object
         */
        public MessageQueue getMessageQueue() {
            return messageQueue;
        }
    }

    /**
     * Partial message handler for receiving binary messages.
     */
    public static class PartialByteBufferCaptureHandler extends AbstractHandler implements
                    MessageHandler.Partial<ByteBuffer> {

        /**
         * Parts of the current message. This list is appended with every non-last part and is
         * cleared after last part of a message has been received.
         */
        private final List<ByteBuffer> currentMessage = new ArrayList<>();

        @Override
        public void onMessage(ByteBuffer messagePart, boolean last) {
            final ByteBuffer bufferCopy = ByteBuffer.allocate(messagePart.capacity());
            bufferCopy.put(messagePart);
            currentMessage.add(bufferCopy);
            if (last) {
                int totalSize = 0;
                for (ByteBuffer bb : currentMessage) {
                    totalSize += bb.capacity();
                }
                final ByteBuffer result = ByteBuffer.allocate(totalSize);
                for (ByteBuffer bb : currentMessage) {
                    result.put(bb);
                }
                final String stringResult = new String(result.array());
                getMessageQueue().add(stringResult);
                currentMessage.clear();
            }

        }

    }
    /**
     * Whole message handler for receiving binary messages.
     */
    public class WholeByteBufferCaptureHandler extends AbstractHandler implements
                    MessageHandler.Whole<ByteBuffer> {

        @Override
        public void onMessage(ByteBuffer message) {
            final String stringResult = new String(message.array());
            getMessageQueue().add(stringResult);

        }
    }

    /**
     * Partial message handler for receiving text messages.
     */
    public static class PartialStringCaptureHandler extends AbstractHandler implements
                    MessageHandler.Partial<String> {

        /**
         * Parts of the current message. This list is appended with every non-last part and is
         * cleared after last part of a message has been received.
         */
        private StringBuilder sb = new StringBuilder();

        @Override
        public void onMessage(String messagePart, boolean last) {
            sb.append(messagePart);
            if (last) {
                getMessageQueue().add(sb.toString());
                sb = new StringBuilder();
            }
        }

    }
    /**
     * Whole message handler for receiving text messages.
     */
    public class WholeStringCaptureHandler extends AbstractHandler implements
                    MessageHandler.Whole<String> {

        @Override
        public void onMessage(String message) {
            getMessageQueue().add(message);

        }
    }

}
