/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 *
 */
package org.apache.cassandra.io.util;

import org.apache.cassandra.config.DatabaseDescriptor;
import org.apache.cassandra.utils.ByteBufferUtil;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.Arrays;

import org.junit.BeforeClass;
import org.junit.Test;

import static org.apache.cassandra.Util.expectEOF;
import static org.apache.cassandra.Util.expectException;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

public class BufferedRandomAccessFileTest
{
    @BeforeClass
    public static void setupDD()
    {
        DatabaseDescriptor.daemonInitialization();
    }

    @Test
    public void testReadAndWrite() throws Exception
    {
        SequentialWriter w = createTempFile("braf");

        // writing string of data to the file
        byte[] data = "Hello".getBytes();
        w.write(data);
        assertEquals(data.length, w.length());
        assertEquals(data.length, w.position());

        w.sync();

        // reading small amount of data from file, this is handled by initial buffer
        try (FileHandle.Builder builder = new FileHandle.Builder(w.getPath()))
        {
            try (FileHandle fh = builder.complete();
                 RandomAccessReader r = fh.createReader())
            {

                byte[] buffer = new byte[data.length];
                assertEquals(data.length, r.read(buffer));
                assertTrue(Arrays.equals(buffer, data)); // we read exactly what we wrote
                assertEquals(r.read(), -1); // nothing more to read EOF
                assert r.bytesRemaining() == 0 && r.isEOF();
            }

            // writing buffer bigger than page size, which will trigger reBuffer()
            byte[] bigData = new byte[RandomAccessReader.DEFAULT_BUFFER_SIZE + 10];

            for (int i = 0; i < bigData.length; i++)
                bigData[i] = 'd';

            long initialPosition = w.position();
            w.write(bigData); // writing data
            assertEquals(w.position(), initialPosition + bigData.length);
            assertEquals(w.length(), initialPosition + bigData.length); // file size should equals to last position

            w.sync();

            // re-opening file in read-only mode
            try (FileHandle fh = builder.complete();
                 RandomAccessReader r = fh.createReader())
            {

                // reading written buffer
                r.seek(initialPosition); // back to initial (before write) position
                data = new byte[bigData.length];
                long sizeRead = 0;
                for (int i = 0; i < data.length; i++)
                {
                    data[i] = (byte) r.read();
                    sizeRead++;
                }

                assertEquals(sizeRead, data.length); // read exactly data.length bytes
                assertEquals(r.getFilePointer(), initialPosition + data.length);
                assertEquals(r.length(), initialPosition + bigData.length);
                assertTrue(Arrays.equals(bigData, data));
                assertTrue(r.bytesRemaining() == 0 && r.isEOF()); // we are at the of the file

                // test readBytes(int) method
                r.seek(0);
                ByteBuffer fileContent = ByteBufferUtil.read(r, (int) w.length());
                assertEquals(fileContent.limit(), w.length());
                assert ByteBufferUtil.string(fileContent).equals("Hello" + new String(bigData));

                // read the same buffer but using readFully(int)
                data = new byte[bigData.length];
                r.seek(initialPosition);
                r.readFully(data);
                assert r.bytesRemaining() == 0 && r.isEOF(); // we should be at EOF
                assertTrue(Arrays.equals(bigData, data));

                // try to read past mark (all methods should return -1)
                data = new byte[10];
                assertEquals(r.read(), -1);
                assertEquals(r.read(data), -1);
                assertEquals(r.read(data, 0, data.length), -1);

                // test read(byte[], int, int)
                r.seek(0);
                data = new byte[20];
                assertEquals(15, r.read(data, 0, 15));
                assertTrue(new String(data).contains("Hellodddddddddd"));
                for (int i = 16; i < data.length; i++)
                {
                    assert data[i] == 0;
                }

                w.finish();
            }
        }
    }

    @Test
    public void testReadAndWriteOnCapacity() throws IOException
    {
        File tmpFile = FileUtils.createTempFile("readtest", "bin");
        try (SequentialWriter w = new SequentialWriter(tmpFile))
        {
            // Fully write the file and sync..
            byte[] in = generateByteArray(RandomAccessReader.DEFAULT_BUFFER_SIZE);
            w.write(in);
    
            try (FileHandle.Builder builder = new FileHandle.Builder(w.getPath());
                 FileHandle fh = builder.complete();
                 RandomAccessReader r = fh.createReader())
            {
                // Read it into a same size array.
                byte[] out = new byte[RandomAccessReader.DEFAULT_BUFFER_SIZE];
                r.read(out);
    
                // Cannot read any more.
                int negone = r.read();
                assert negone == -1 : "We read past the end of the file, should have gotten EOF -1. Instead, " + negone;
    
                w.finish();
            }
        }
    }

    @Test
    public void testLength() throws IOException
    {
        File tmpFile = FileUtils.createTempFile("lengthtest", "bin");
        try (SequentialWriter w = new SequentialWriter(tmpFile))
        {
            assertEquals(0, w.length());
    
            // write a chunk smaller then our buffer, so will not be flushed
            // to disk
            byte[] lessThenBuffer = generateByteArray(RandomAccessReader.DEFAULT_BUFFER_SIZE / 2);
            w.write(lessThenBuffer);
            assertEquals(lessThenBuffer.length, w.length());
    
            // sync the data and check length
            w.sync();
            assertEquals(lessThenBuffer.length, w.length());
    
            // write more then the buffer can hold and check length
            byte[] biggerThenBuffer = generateByteArray(RandomAccessReader.DEFAULT_BUFFER_SIZE * 2);
            w.write(biggerThenBuffer);
            assertEquals(biggerThenBuffer.length + lessThenBuffer.length, w.length());
    
            w.finish();
    
            // will use cachedlength
            try (FileHandle.Builder builder = new FileHandle.Builder(tmpFile.path());
                 FileHandle fh = builder.complete();
                 RandomAccessReader r = fh.createReader())
            {
                assertEquals(lessThenBuffer.length + biggerThenBuffer.length, r.length());
            }
        }
    }

    @Test
    public void testReadBytes() throws IOException
    {
        final SequentialWriter w = createTempFile("brafReadBytes");

        byte[] data = new byte[RandomAccessReader.DEFAULT_BUFFER_SIZE + 10];

        for (int i = 0; i < data.length; i++)
        {
            data[i] = 'c';
        }

        w.write(data);
        w.sync();

        try (FileHandle.Builder builder = new FileHandle.Builder(w.getPath());
             FileHandle fh = builder.complete();
             RandomAccessReader r = fh.createReader())
        {

            ByteBuffer content = ByteBufferUtil.read(r, (int) r.length());

            // after reading whole file we should be at EOF
            assertEquals(0, ByteBufferUtil.compare(content, data));
            assert r.bytesRemaining() == 0 && r.isEOF();

            r.seek(0);
            content = ByteBufferUtil.read(r, 10); // reading first 10 bytes
            assertEquals(ByteBufferUtil.compare(content, "cccccccccc".getBytes()), 0);
            assertEquals(r.bytesRemaining(), r.length() - content.limit());

            // trying to read more than file has right now
            expectEOF(() -> ByteBufferUtil.read(r, (int) r.length() + 10));

            w.finish();
        }
    }

    @Test
    public void testSeek() throws Exception
    {
        SequentialWriter w = createTempFile("brafSeek");
        byte[] data = generateByteArray(RandomAccessReader.DEFAULT_BUFFER_SIZE + 20);
        w.write(data);
        w.finish();

        try (FileHandle.Builder builder = new FileHandle.Builder(w.getPath());
             FileHandle fh = builder.complete();
             RandomAccessReader file = fh.createReader())
        {
            file.seek(0);
            assertEquals(file.getFilePointer(), 0);
            assertEquals(file.bytesRemaining(), file.length());

            file.seek(20);
            assertEquals(file.getFilePointer(), 20);
            assertEquals(file.bytesRemaining(), file.length() - 20);

            // trying to seek past the end of the file should produce EOFException
            expectException(() -> {
                file.seek(file.length() + 30);
                return null;
            }, IllegalArgumentException.class);

            expectException(() -> {
                file.seek(-1);
                return null;
            }, IllegalArgumentException.class); // throws IllegalArgumentException
        }
    }

    @Test
    public void testSkipBytes() throws IOException
    {
        SequentialWriter w = createTempFile("brafSkipBytes");
        w.write(generateByteArray(RandomAccessReader.DEFAULT_BUFFER_SIZE * 2));
        w.finish();

        try (FileHandle.Builder builder = new FileHandle.Builder(w.getPath());
             FileHandle fh = builder.complete();
             RandomAccessReader file = fh.createReader())
        {

            file.seek(0); // back to the beginning of the file
            assertEquals(file.skipBytes(10), 10);
            assertEquals(file.bytesRemaining(), file.length() - 10);

            int initialPosition = (int) file.getFilePointer();
            // can't skip more than file size
            assertEquals(file.skipBytes((int) file.length() + 10), file.length() - initialPosition);
            assertEquals(file.getFilePointer(), file.length());
            assert file.bytesRemaining() == 0 && file.isEOF();

            file.seek(0);

            // skipping negative amount should return 0
            assertEquals(file.skipBytes(-1000), 0);
            assertEquals(file.getFilePointer(), 0);
            assertEquals(file.bytesRemaining(), file.length());
        }
    }

    @Test
    public void testGetFilePointer() throws IOException
    {
        final SequentialWriter w = createTempFile("brafGetFilePointer");

        assertEquals(w.position(), 0); // initial position should be 0

        w.write(generateByteArray(20));
        assertEquals(w.position(), 20); // position 20 after writing 20 bytes

        w.sync();

        try (FileHandle.Builder builder = new FileHandle.Builder(w.getPath());
             FileHandle fh = builder.complete();
             RandomAccessReader r = fh.createReader())
        {

            // position should change after skip bytes
            r.seek(0);
            r.skipBytes(15);
            assertEquals(r.getFilePointer(), 15);

            r.read();
            assertEquals(r.getFilePointer(), 16);
            r.read(new byte[4]);
            assertEquals(r.getFilePointer(), 20);

            w.finish();
        }
    }

    @Test
    public void testGetPath() throws IOException
    {
        SequentialWriter file = createTempFile("brafGetPath");
        assert file.getPath().contains("brafGetPath");
        file.finish();
    }

    @Test
    public void testIsEOF() throws IOException
    {
        for (int bufferSize : Arrays.asList(1, 2, 3, 5, 8, 64))  // smaller, equal, bigger buffer sizes
        {
            final byte[] target = new byte[32];

            // single too-large read
            for (final int offset : Arrays.asList(0, 8))
            {
                File file1 = writeTemporaryFile(new byte[16]);
                try (FileHandle.Builder builder = new FileHandle.Builder(file1.path()).bufferSize(bufferSize);
                     FileHandle fh = builder.complete();
                     RandomAccessReader file = fh.createReader())
                {
                    expectEOF(() -> { file.readFully(target, offset, 17); return null; });
                }
            }

            // first read is ok but eventually EOFs
            for (final int n : Arrays.asList(1, 2, 4, 8))
            {
                File file1 = writeTemporaryFile(new byte[16]);
                try (FileHandle.Builder builder = new FileHandle.Builder(file1.path()).bufferSize(bufferSize);
                     FileHandle fh = builder.complete();
                     RandomAccessReader file = fh.createReader())
                {
                    expectEOF(() -> {
                        while (true)
                            file.readFully(target, 0, n);
                    });
                }
            }
        }
    }

    @Test
    public void testNotEOF() throws IOException
    {
        try (final RandomAccessReader reader = RandomAccessReader.open(writeTemporaryFile(new byte[1])))
        {
            assertEquals(1, reader.read(new byte[2]));
        }
    }

    @Test
    public void testBytesRemaining() throws IOException
    {
        SequentialWriter w = createTempFile("brafBytesRemaining");

        int toWrite = RandomAccessReader.DEFAULT_BUFFER_SIZE + 10;

        w.write(generateByteArray(toWrite));

        w.sync();

        try (FileHandle.Builder builder = new FileHandle.Builder(w.getPath());
             FileHandle fh = builder.complete();
             RandomAccessReader r = fh.createReader())
        {

            assertEquals(r.bytesRemaining(), toWrite);

            for (int i = 1; i <= r.length(); i++)
            {
                r.read();
                assertEquals(r.bytesRemaining(), r.length() - i);
            }

            r.seek(0);
            r.skipBytes(10);
            assertEquals(r.bytesRemaining(), r.length() - 10);

            w.finish();
        }
    }

    @Test
    public void testBytesPastMark() throws IOException
    {
        File tmpFile = FileUtils.createTempFile("overflowtest", "bin");
        tmpFile.deleteOnExit();

        // Create the BRAF by filename instead of by file.
        try (FileHandle.Builder builder = new FileHandle.Builder(tmpFile.path());
             FileHandle fh = builder.complete();
             RandomAccessReader r = fh.createReader())
        {
            assert tmpFile.path().equals(r.getPath());

            // Create a mark and move the rw there.
            final DataPosition mark = r.mark();
            r.reset(mark);

            // Expect this call to succeed.
            r.bytesPastMark(mark);
        }
    }

    @Test
    public void testClose() throws IOException
    {
        final SequentialWriter w = createTempFile("brafClose");

        byte[] data = generateByteArray(RandomAccessReader.DEFAULT_BUFFER_SIZE + 20);

        w.write(data);
        w.finish();

        final RandomAccessReader r = RandomAccessReader.open(new File(w.getPath()));

        r.close(); // closing to test read after close

        expectException(() -> r.read(), NullPointerException.class);

        //Used to throw ClosedChannelException, but now that it extends BDOSP it just NPEs on the buffer
        //Writing to a BufferedOutputStream that is closed generates no error
        //Going to allow the NPE to throw to catch as a bug any use after close. Notably it won't throw NPE for a
        //write of a 0 length, but that is kind of a corner case
        expectException(() -> { w.write(generateByteArray(1)); return null; }, NullPointerException.class);

        try (RandomAccessReader copy = RandomAccessReader.open(new File(r.getPath())))
        {
            ByteBuffer contents = ByteBufferUtil.read(copy, (int) copy.length());

            assertEquals(contents.limit(), data.length);
            assertEquals(ByteBufferUtil.compare(contents, data), 0);
        }
    }

    @Test
    public void testMarkAndReset() throws IOException
    {
        SequentialWriter w = createTempFile("brafTestMark");
        w.write(new byte[30]);

        w.finish();

        try (FileHandle.Builder builder = new FileHandle.Builder(w.getPath());
             FileHandle fh = builder.complete();
             RandomAccessReader file = fh.createReader())
        {
            file.seek(10);
            DataPosition mark = file.mark();

            file.seek(file.length());
            assertTrue(file.isEOF());

            file.reset();
            assertEquals(file.bytesRemaining(), 20);

            file.seek(file.length());
            assertTrue(file.isEOF());

            file.reset(mark);
            assertEquals(file.bytesRemaining(), 20);

            file.seek(file.length());
            assertEquals(file.bytesPastMark(), 20);
            assertEquals(file.bytesPastMark(mark), 20);

            file.reset(mark);
            assertEquals(file.bytesPastMark(), 0);
        }
    }

    @Test(expected = AssertionError.class)
    public void testAssertionErrorWhenBytesPastMarkIsNegative() throws IOException
    {
        try (SequentialWriter w = createTempFile("brafAssertionErrorWhenBytesPastMarkIsNegative"))
        {
            w.write(new byte[30]);
            w.flush();

            try (FileHandle.Builder builder = new FileHandle.Builder(w.getPath());
                 FileHandle fh = builder.complete();
                 RandomAccessReader r = fh.createReader())
            {
                r.seek(10);
                r.mark();

                r.seek(0);
                r.bytesPastMark();
            }
        }
    }

    @Test
    public void testReadOnly() throws IOException
    {
        SequentialWriter file = createTempFile("brafReadOnlyTest");

        byte[] data = new byte[20];
        for (int i = 0; i < data.length; i++)
            data[i] = 'c';

        file.write(data);
        file.sync(); // flushing file to the disk

        // read-only copy of the file, with fixed file length
        final RandomAccessReader copy = RandomAccessReader.open(new File(file.getPath()));

        copy.seek(copy.length());
        assertTrue(copy.bytesRemaining() == 0 && copy.isEOF());

        // can't seek past the end of the file for read-only files
        expectException(() -> { copy.seek(copy.length() + 1); return null; }, IllegalArgumentException.class);

        copy.seek(0);
        copy.skipBytes(5);

        assertEquals(copy.bytesRemaining(), 15);
        assertEquals(copy.getFilePointer(), 5);
        assertTrue(!copy.isEOF());

        copy.seek(0);
        ByteBuffer contents = ByteBufferUtil.read(copy, (int) copy.length());

        assertEquals(contents.limit(), copy.length());
        assertTrue(ByteBufferUtil.compare(contents, data) == 0);

        copy.seek(0);

        int count = 0;
        while (!copy.isEOF())
        {
            assertEquals((byte) copy.read(), 'c');
            count++;
        }

        assertEquals(count, copy.length());

        copy.seek(0);
        byte[] content = new byte[10];
        copy.read(content);

        assertEquals(new String(content), "cccccccccc");

        file.finish();
        copy.close();
    }

    @Test (expected=IllegalArgumentException.class)
    public void testSetNegativeLength() throws IOException, IllegalArgumentException
    {
        File tmpFile = FileUtils.createTempFile("set_negative_length", "bin");
        try (SequentialWriter file = new SequentialWriter(tmpFile))
        {
            file.truncate(-8L);
        }
    }

    private SequentialWriter createTempFile(String name) throws IOException
    {
        File tempFile = FileUtils.createTempFile(name, null);
        tempFile.deleteOnExit();

        return new SequentialWriter(tempFile);
    }

    private File writeTemporaryFile(byte[] data) throws IOException
    {
        File f = FileUtils.createTempFile("BRAFTestFile", null);
        f.deleteOnExit();
        FileOutputStreamPlus fout = new FileOutputStreamPlus(f);
        fout.write(data);
        fout.sync();
        fout.close();
        return f;
    }

    private byte[] generateByteArray(int length)
    {
        byte[] arr = new byte[length];

        for (int i = 0; i < length; i++)
            arr[i] = 'a';

        return arr;
    }
}
