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


import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.nio.BufferOverflowException;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.concurrent.ThreadLocalRandom;

import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.junit.Assert;
import org.junit.Ignore;
import org.junit.Test;

import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;

public class BufferUtilTest
{
    @Test
    public void testToInt() throws Exception
    {
        ByteBuffer buf[] =
        {
            BufferUtil.toBuffer("0"),
            BufferUtil.toBuffer(" 42 "),
            BufferUtil.toBuffer("   43abc"),
            BufferUtil.toBuffer("-44"),
            BufferUtil.toBuffer(" - 45;"),
            BufferUtil.toBuffer("-2147483648"),
            BufferUtil.toBuffer("2147483647"),
        };

        int val[] =
        {
            0,42,43,-44,-45,-2147483648,2147483647
        };

        for (int i=0;i<buf.length;i++)
            assertEquals("t"+i, val[i], BufferUtil.toInt(buf[i]));
    }

    @Test
    public void testPutInt() throws Exception
    {
        int val[] =
        {
            0,42,43,-44,-45,Integer.MIN_VALUE,Integer.MAX_VALUE
        };

        String str[] =
        {
            "0","42","43","-44","-45",""+Integer.MIN_VALUE,""+Integer.MAX_VALUE
        };

        ByteBuffer buffer = ByteBuffer.allocate(24);

        for (int i=0;i<val.length;i++)
        {
            BufferUtil.clearToFill(buffer);
            BufferUtil.putDecInt(buffer,val[i]);
            BufferUtil.flipToFlush(buffer,0);
            assertEquals("t"+i,str[i],BufferUtil.toString(buffer));
        }
    }

    @Test
    public void testPutLong() throws Exception
    {
        long val[] =
        {
                0L,42L,43L,-44L,-45L,Long.MIN_VALUE,Long.MAX_VALUE
        };

        String str[] =
        {
                "0","42","43","-44","-45",""+Long.MIN_VALUE,""+Long.MAX_VALUE
        };

        ByteBuffer buffer = ByteBuffer.allocate(50);

        for (int i=0;i<val.length;i++)
        {
            BufferUtil.clearToFill(buffer);
            BufferUtil.putDecLong(buffer,val[i]);
            BufferUtil.flipToFlush(buffer,0);
            assertEquals("t"+i,str[i],BufferUtil.toString(buffer));
        }
    }

    @Test
    public void testPutHexInt() throws Exception
    {
        int val[] =
        {
            0,42,43,-44,-45,-2147483648,2147483647
        };

        String str[] =
        {
            "0","2A","2B","-2C","-2D","-80000000","7FFFFFFF"
        };

        ByteBuffer buffer = ByteBuffer.allocate(50);

        for (int i=0;i<val.length;i++)
        {
            BufferUtil.clearToFill(buffer);
            BufferUtil.putHexInt(buffer,val[i]);
            BufferUtil.flipToFlush(buffer,0);
            assertEquals("t"+i,str[i],BufferUtil.toString(buffer));
        }
    }

    @Test
    public void testPut() throws Exception
    {
        ByteBuffer to = BufferUtil.allocate(10);
        ByteBuffer from=BufferUtil.toBuffer("12345");

        BufferUtil.clear(to);
        assertEquals(5,BufferUtil.append(to,from));
        assertTrue(BufferUtil.isEmpty(from));
        assertEquals("12345",BufferUtil.toString(to));

        from=BufferUtil.toBuffer("XX67890ZZ");
        from.position(2);

        assertEquals(5,BufferUtil.append(to,from));
        assertEquals(2,from.remaining());
        assertEquals("1234567890",BufferUtil.toString(to));
    }



    @Test
    public void testAppend() throws Exception
    {
        ByteBuffer to = BufferUtil.allocate(8);
        ByteBuffer from=BufferUtil.toBuffer("12345");

        BufferUtil.append(to,from.array(),0,3);
        assertEquals("123",BufferUtil.toString(to));
        BufferUtil.append(to,from.array(),3,2);
        assertEquals("12345",BufferUtil.toString(to));

        try
        {
            BufferUtil.append(to,from.array(),0,5);
            Assert.fail();
        }
        catch(BufferOverflowException e)
        {}
    }


    @Test
    public void testPutDirect() throws Exception
    {
        ByteBuffer to = BufferUtil.allocateDirect(10);
        ByteBuffer from=BufferUtil.toBuffer("12345");

        BufferUtil.clear(to);
        assertEquals(5,BufferUtil.append(to,from));
        assertTrue(BufferUtil.isEmpty(from));
        assertEquals("12345",BufferUtil.toString(to));

        from=BufferUtil.toBuffer("XX67890ZZ");
        from.position(2);

        assertEquals(5,BufferUtil.append(to,from));
        assertEquals(2,from.remaining());
        assertEquals("1234567890",BufferUtil.toString(to));
    }

    @Test
    public void testToBuffer_Array()
    {
        byte arr[] = new byte[128];
        Arrays.fill(arr,(byte)0x44);
        ByteBuffer buf = BufferUtil.toBuffer(arr);

        int count = 0;
        while (buf.remaining() > 0)
        {
            byte b = buf.get();
            Assert.assertEquals(b,0x44);
            count++;
        }

        Assert.assertEquals("Count of bytes",arr.length,count);
    }

    @Test
    public void testToBuffer_ArrayOffsetLength()
    {
        byte arr[] = new byte[128];
        Arrays.fill(arr,(byte)0xFF); // fill whole thing with FF
        int offset = 10;
        int length = 100;
        Arrays.fill(arr,offset,offset + length,(byte)0x77); // fill partial with 0x77
        ByteBuffer buf = BufferUtil.toBuffer(arr,offset,length);

        int count = 0;
        while (buf.remaining() > 0)
        {
            byte b = buf.get();
            Assert.assertEquals(b,0x77);
            count++;
        }

        Assert.assertEquals("Count of bytes",length,count);
    }

    private static final Logger LOG = Log.getLogger(BufferUtilTest.class);

    @Test
    @Ignore("Very simple microbenchmark to compare different writeTo implementations. Only for development thus " +
            "ignored.")
    public void testWriteToMicrobenchmark() throws IOException
    {
        int capacity = 1024 * 128;
        int iterations = 100;
        int testRuns = 10;
        byte[] bytes = new byte[capacity];
        ThreadLocalRandom.current().nextBytes(bytes);
        ByteBuffer buffer = BufferUtil.allocate(capacity);
        BufferUtil.append(buffer, bytes, 0, capacity);
        long startTest = System.nanoTime();
        for (int i = 0; i < testRuns; i++)
        {
            long start = System.nanoTime();
            for (int j = 0; j < iterations; j++)
            {
                ByteArrayOutputStream out = new ByteArrayOutputStream();
                long startRun = System.nanoTime();
                BufferUtil.writeTo(buffer.asReadOnlyBuffer(), out);
                long elapsedRun = System.nanoTime() - startRun;
//                LOG.warn("run elapsed={}ms", elapsedRun / 1000);
                assertThat("Bytes in out equal bytes in buffer", Arrays.equals(bytes, out.toByteArray()), is(true));
            }
            long elapsed = System.nanoTime() - start;
            LOG.warn("elapsed={}ms average={}ms", elapsed / 1000, elapsed/iterations/1000);
        }
        LOG.warn("overall average: {}ms", (System.nanoTime() - startTest) / testRuns / iterations / 1000);
    }

    @Test
    public void testWriteToWithBufferThatDoesNotExposeArrayAndSmallContent() throws IOException
    {
        int capacity = BufferUtil.TEMP_BUFFER_SIZE/4;
        testWriteToWithBufferThatDoesNotExposeArray(capacity);
    }

    @Test
    public void testWriteToWithBufferThatDoesNotExposeArrayAndContentLengthMatchingTempBufferSize() throws IOException
    {
        int capacity = BufferUtil.TEMP_BUFFER_SIZE;
        testWriteToWithBufferThatDoesNotExposeArray(capacity);
    }

    @Test
    public void testWriteToWithBufferThatDoesNotExposeArrayAndContentSlightlyBiggerThanTwoTimesTempBufferSize()
            throws
            IOException
    {
        int capacity = BufferUtil.TEMP_BUFFER_SIZE*2+1024;
        testWriteToWithBufferThatDoesNotExposeArray(capacity);
    }


    @Test
    public void testEnsureCapacity() throws Exception
    {
        ByteBuffer b = BufferUtil.toBuffer("Goodbye Cruel World");
        assertTrue(b==BufferUtil.ensureCapacity(b, 0));
        assertTrue(b==BufferUtil.ensureCapacity(b, 10));
        assertTrue(b==BufferUtil.ensureCapacity(b, b.capacity()));


        ByteBuffer b1 = BufferUtil.ensureCapacity(b, 64);
        assertTrue(b!=b1);
        assertEquals(64, b1.capacity());
        assertEquals("Goodbye Cruel World", BufferUtil.toString(b1));

        b1.position(8);
        b1.limit(13);
        assertEquals("Cruel", BufferUtil.toString(b1));
        ByteBuffer b2 = b1.slice();
        assertEquals("Cruel", BufferUtil.toString(b2));
        System.err.println(BufferUtil.toDetailString(b2));
        assertEquals(8, b2.arrayOffset());
        assertEquals(5, b2.capacity());

        assertTrue(b2==BufferUtil.ensureCapacity(b2, 5));

        ByteBuffer b3 = BufferUtil.ensureCapacity(b2, 64);
        assertTrue(b2!=b3);
        assertEquals(64, b3.capacity());
        assertEquals("Cruel", BufferUtil.toString(b3));
        assertEquals(0, b3.arrayOffset());

    }


    private void testWriteToWithBufferThatDoesNotExposeArray(int capacity) throws IOException
    {
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        byte[] bytes = new byte[capacity];
        ThreadLocalRandom.current().nextBytes(bytes);
        ByteBuffer buffer = BufferUtil.allocate(capacity);
        BufferUtil.append(buffer, bytes, 0, capacity);
        BufferUtil.writeTo(buffer.asReadOnlyBuffer(), out);
        assertThat("Bytes in out equal bytes in buffer", Arrays.equals(bytes, out.toByteArray()), is(true));
    }

    @Test
    public void testMappedFile() throws Exception
    {
        String data="Now is the time for all good men to come to the aid of the party";
        File file = File.createTempFile("test",".txt");
        file.deleteOnExit();
        try(FileWriter out = new FileWriter(file);)
        {
            out.write(data);
        }

        ByteBuffer mapped = BufferUtil.toMappedBuffer(file);
        assertEquals(data,BufferUtil.toString(mapped));
        assertTrue(BufferUtil.isMappedBuffer(mapped));

        ByteBuffer direct = BufferUtil.allocateDirect(data.length());
        BufferUtil.clearToFill(direct);
        direct.put(data.getBytes(StandardCharsets.ISO_8859_1));
        BufferUtil.flipToFlush(direct, 0);
        assertEquals(data,BufferUtil.toString(direct));
        assertFalse(BufferUtil.isMappedBuffer(direct));

        ByteBuffer slice = direct.slice();
        assertEquals(data,BufferUtil.toString(slice));
        assertFalse(BufferUtil.isMappedBuffer(slice));

        ByteBuffer duplicate = direct.duplicate();
        assertEquals(data,BufferUtil.toString(duplicate));
        assertFalse(BufferUtil.isMappedBuffer(duplicate));

        ByteBuffer readonly = direct.asReadOnlyBuffer();
        assertEquals(data,BufferUtil.toString(readonly));
        assertFalse(BufferUtil.isMappedBuffer(readonly));
    }
}
