//
//  ========================================================================
//  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.io;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousServerSocketChannel;
import java.nio.channels.AsynchronousSocketChannel;
import java.nio.channels.FileChannel;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.charset.StandardCharsets;
import java.nio.file.StandardOpenOption;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
import org.eclipse.jetty.toolchain.test.OS;
import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.IO;
import org.junit.Assert;
import org.junit.Test;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

public class IOTest
{
    @Test
    public void testIO() throws Exception
    {
        // Only a little test
        ByteArrayInputStream in = new ByteArrayInputStream("The quick brown fox jumped over the lazy dog".getBytes());
        ByteArrayOutputStream out = new ByteArrayOutputStream();

        IO.copy(in, out);

        assertEquals("copyThread", out.toString(), "The quick brown fox jumped over the lazy dog");
    }

    @Test
    public void testHalfClose() throws Exception
    {
        ServerSocket connector = new ServerSocket(0);

        Socket client = new Socket("localhost", connector.getLocalPort());
        Socket server = connector.accept();

        // we can write both ways
        client.getOutputStream().write(1);
        assertEquals(1, server.getInputStream().read());
        server.getOutputStream().write(1);
        assertEquals(1, client.getInputStream().read());

        // shutdown output results in read -1
        client.shutdownOutput();
        assertEquals(-1, server.getInputStream().read());

        // Even though EOF has been read, the server input is not seen as shutdown
        assertFalse(server.isInputShutdown());

        // and we can read -1 again
        assertEquals(-1, server.getInputStream().read());

        // but cannot write
        try
        {
            client.getOutputStream().write(1);
            fail("exception expected");
        }
        catch (SocketException e)
        {
        }

        // but can still write in opposite direction.
        server.getOutputStream().write(1);
        assertEquals(1, client.getInputStream().read());

        // server can shutdown input to match the shutdown out of client
        server.shutdownInput();

        // now we EOF instead of reading -1
        try
        {
            server.getInputStream().read();
            fail("exception expected");
        }
        catch (SocketException e)
        {
        }

        // but can still write in opposite direction.
        server.getOutputStream().write(1);
        assertEquals(1, client.getInputStream().read());

        // client can shutdown input
        client.shutdownInput();

        // now we EOF instead of reading -1
        try
        {
            client.getInputStream().read();
            fail("exception expected");
        }
        catch (SocketException e)
        {
        }

        // But we can still write at the server (data which will never be read)
        server.getOutputStream().write(1);

        // and the server output is not shutdown
        assertFalse(server.isOutputShutdown());

        // until we explictly shut it down
        server.shutdownOutput();

        // and now we can't write
        try
        {
            server.getOutputStream().write(1);
            fail("exception expected");
        }
        catch (SocketException e)
        {
        }

        // but the sockets are still open
        assertFalse(client.isClosed());
        assertFalse(server.isClosed());

        // but if we close one end
        client.close();

        // it is seen as closed.
        assertTrue(client.isClosed());

        // but not the other end
        assertFalse(server.isClosed());

        // which has to be closed explictly
        server.close();
        assertTrue(server.isClosed());
    }

    @Test
    public void testHalfCloseClientServer() throws Exception
    {
        ServerSocketChannel connector = ServerSocketChannel.open();
        connector.socket().bind(null);

        Socket client = SocketChannel.open(connector.socket().getLocalSocketAddress()).socket();
        client.setSoTimeout(1000);
        client.setSoLinger(false, -1);
        Socket server = connector.accept().socket();
        server.setSoTimeout(1000);
        server.setSoLinger(false, -1);

        // Write from client to server
        client.getOutputStream().write(1);

        // Server reads
        assertEquals(1, server.getInputStream().read());

        // Write from server to client with oshut
        server.getOutputStream().write(1);
        // System.err.println("OSHUT "+server);
        server.shutdownOutput();

        // Client reads response
        assertEquals(1, client.getInputStream().read());

        try
        {
            // Client reads -1 and does ishut
            assertEquals(-1, client.getInputStream().read());
            assertFalse(client.isInputShutdown());
            //System.err.println("ISHUT "+client);
            client.shutdownInput();

            // Client ???
            //System.err.println("OSHUT "+client);
            client.shutdownOutput();
            //System.err.println("CLOSE "+client);
            client.close();

            // Server reads -1, does ishut and then close
            assertEquals(-1, server.getInputStream().read());
            assertFalse(server.isInputShutdown());
            //System.err.println("ISHUT "+server);

            try
            {
                server.shutdownInput();
            }
            catch (SocketException e)
            {
                // System.err.println(e);
            }
            //System.err.println("CLOSE "+server);
            server.close();

        }
        catch (Exception e)
        {
            System.err.println(e);
            assertTrue(OS.IS_OSX);
        }
    }

    @Test
    public void testHalfCloseBadClient() throws Exception
    {
        ServerSocketChannel connector = ServerSocketChannel.open();
        connector.socket().bind(null);

        Socket client = SocketChannel.open(connector.socket().getLocalSocketAddress()).socket();
        client.setSoTimeout(1000);
        client.setSoLinger(false, -1);
        Socket server = connector.accept().socket();
        server.setSoTimeout(1000);
        server.setSoLinger(false, -1);

        // Write from client to server
        client.getOutputStream().write(1);

        // Server reads
        assertEquals(1, server.getInputStream().read());

        // Write from server to client with oshut
        server.getOutputStream().write(1);
        //System.err.println("OSHUT "+server);
        server.shutdownOutput();

        try
        {
            // Client reads response
            assertEquals(1, client.getInputStream().read());

            // Client reads -1
            assertEquals(-1, client.getInputStream().read());
            assertFalse(client.isInputShutdown());

            // Client can still write as we are half closed
            client.getOutputStream().write(1);

            // Server can still read
            assertEquals(1, server.getInputStream().read());

            // Server now closes
            server.close();

            // Client still reads -1 (not broken pipe !!)
            assertEquals(-1, client.getInputStream().read());
            assertFalse(client.isInputShutdown());

            Thread.sleep(100);

            // Client still reads -1 (not broken pipe !!)
            assertEquals(-1, client.getInputStream().read());
            assertFalse(client.isInputShutdown());

            // Client can still write data even though server is closed???
            client.getOutputStream().write(1);

            // Client eventually sees Broken Pipe
            int i = 0;
            try
            {
                for (i = 0; i < 100000; i++)
                    client.getOutputStream().write(1);

                Assert.fail();
            }
            catch (IOException e)
            {
            }
            client.close();

        }
        catch (Exception e)
        {
            System.err.println("PLEASE INVESTIGATE:");
            e.printStackTrace();
        }
    }

    @Test
    public void testServerChannelInterrupt() throws Exception
    {
        final ServerSocketChannel connector = ServerSocketChannel.open();
        connector.configureBlocking(true);
        connector.socket().bind(null);

        Socket client = SocketChannel.open(connector.socket().getLocalSocketAddress()).socket();
        client.setSoTimeout(2000);
        client.setSoLinger(false, -1);
        Socket server = connector.accept().socket();
        server.setSoTimeout(2000);
        server.setSoLinger(false, -1);

        // Write from client to server
        client.getOutputStream().write(1);
        // Server reads
        assertEquals(1, server.getInputStream().read());

        // Write from server to client
        server.getOutputStream().write(1);
        // Client reads
        assertEquals(1, client.getInputStream().read());


        // block a thread in accept
        final CountDownLatch alatch=new CountDownLatch(2);
        Thread acceptor = new Thread()
        {
            @Override
            public void run()
            {
                try
                {
                    alatch.countDown();
                    connector.accept();
                }
                catch (Throwable e)
                {
                }
                finally
                {
                    alatch.countDown();
                }
            }
        };
        acceptor.start();
        while (alatch.getCount()==2)
            Thread.sleep(10);

        // interrupt the acceptor
        acceptor.interrupt();

        // wait for acceptor to exit
        assertTrue(alatch.await(10,TimeUnit.SECONDS));

        // connector is closed
        assertFalse(connector.isOpen());

        // but connection is still open
        assertFalse(client.isClosed());
        assertFalse(server.isClosed());

        // Write from client to server
        client.getOutputStream().write(42);
        // Server reads
        assertEquals(42, server.getInputStream().read());

        // Write from server to client
        server.getOutputStream().write(43);
        // Client reads
        assertEquals(43, client.getInputStream().read());

        client.close();

    }



    @Test
    public void testReset() throws Exception
    {
        try (ServerSocket connector = new ServerSocket(0);
            Socket client = new Socket("127.0.0.1", connector.getLocalPort());
            Socket server = connector.accept();)
        {
            client.setTcpNoDelay(true);
            client.setSoLinger(true, 0);
            server.setTcpNoDelay(true);
            server.setSoLinger(true, 0);

            client.getOutputStream().write(1);
            assertEquals(1, server.getInputStream().read());
            server.getOutputStream().write(1);
            assertEquals(1, client.getInputStream().read());

            // Server generator shutdowns output after non persistent sending response.
            server.shutdownOutput();

            // client endpoint reads EOF and shutdown input as result
            assertEquals(-1, client.getInputStream().read());
            client.shutdownInput();

            // client connection see's EOF and shutsdown output as no more requests to be sent.
            client.shutdownOutput();

            // Since input already shutdown, client also closes socket.
            client.close();

            // Server reads the EOF from client oshut and shut's down it's input
            assertEquals(-1, server.getInputStream().read());
            server.shutdownInput();

            // Since output was already shutdown, server closes
            server.close();
        }
    }

    @Test
    public void testAsyncSocketChannel() throws Exception
    {
        AsynchronousServerSocketChannel connector = AsynchronousServerSocketChannel.open();
        connector.bind(null);
        InetSocketAddress addr=(InetSocketAddress)connector.getLocalAddress();
        Future<AsynchronousSocketChannel> acceptor = connector.accept();

        AsynchronousSocketChannel client = AsynchronousSocketChannel.open();

        client.connect(new InetSocketAddress("127.0.0.1",addr.getPort())).get(5, TimeUnit.SECONDS);

        AsynchronousSocketChannel server = acceptor.get(5, TimeUnit.SECONDS);

        ByteBuffer read = ByteBuffer.allocate(1024);
        Future<Integer> reading = server.read(read);

        byte[] data = "Testing 1 2 3".getBytes(StandardCharsets.UTF_8);
        ByteBuffer write = BufferUtil.toBuffer(data);
        Future<Integer> writing = client.write(write);

        writing.get(5, TimeUnit.SECONDS);
        reading.get(5, TimeUnit.SECONDS);
        read.flip();

        Assert.assertEquals(ByteBuffer.wrap(data), read);
    }

    @Test
    public void testGatherWrite() throws Exception
    {
        File dir = MavenTestingUtils.getTargetTestingDir();
        if (!dir.exists())
            dir.mkdir();

        File file = File.createTempFile("test",".txt",dir);
        file.deleteOnExit();
        FileChannel out = FileChannel.open(file.toPath(),
                StandardOpenOption.CREATE,
                StandardOpenOption.READ,
                StandardOpenOption.WRITE,
                StandardOpenOption.DELETE_ON_CLOSE);

        ByteBuffer[] buffers = new ByteBuffer[4096];
        long expected=0;
        for (int i=0;i<buffers.length;i++)
        {
            buffers[i]=BufferUtil.toBuffer(i);
            expected+=buffers[i].remaining();
        }

        long wrote = IO.write(out,buffers,0,buffers.length);

        assertEquals(expected,wrote);

        for (int i=0;i<buffers.length;i++)
            assertEquals(0,buffers[i].remaining());
    }
}
