/*
 * 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.commons.compress.utils;

import org.junit.Ignore;
import org.junit.Test;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.ClosedChannelException;
import java.nio.channels.SeekableByteChannel;
import java.util.Arrays;

import static java.nio.charset.StandardCharsets.*;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;

public class SeekableInMemoryByteChannelTest {

    private final byte[] testData = "Some data".getBytes(UTF_8);

    @Test
    public void shouldReadContentsProperly() throws IOException {
        //given
        final SeekableInMemoryByteChannel c = new SeekableInMemoryByteChannel(testData);
        final ByteBuffer readBuffer = ByteBuffer.allocate(testData.length);
        //when
        final int readCount = c.read(readBuffer);
        //then
        assertEquals(testData.length, readCount);
        assertArrayEquals(testData, readBuffer.array());
        assertEquals(testData.length, c.position());
        c.close();
    }

    @Test
    public void shouldReadContentsWhenBiggerBufferSupplied() throws IOException {
        //given
        final SeekableInMemoryByteChannel c = new SeekableInMemoryByteChannel(testData);
        final ByteBuffer readBuffer = ByteBuffer.allocate(testData.length + 1);
        //when
        final int readCount = c.read(readBuffer);
        //then
        assertEquals(testData.length, readCount);
        assertArrayEquals(testData, Arrays.copyOf(readBuffer.array(), testData.length));
        assertEquals(testData.length, c.position());
        c.close();
    }

    @Test
    public void shouldReadDataFromSetPosition() throws IOException {
        //given
        final SeekableInMemoryByteChannel c = new SeekableInMemoryByteChannel(testData);
        final ByteBuffer readBuffer = ByteBuffer.allocate(4);
        //when
        c.position(5L);
        final int readCount = c.read(readBuffer);
        //then
        assertEquals(4L, readCount);
        assertEquals("data", new String(readBuffer.array(), UTF_8));
        assertEquals(testData.length, c.position());
        c.close();
    }

    @Test
    public void shouldSignalEOFWhenPositionAtTheEnd() throws IOException {
        //given
        final SeekableInMemoryByteChannel c = new SeekableInMemoryByteChannel(testData);
        final ByteBuffer readBuffer = ByteBuffer.allocate(testData.length);
        //when
        c.position(testData.length + 1);
        final int readCount = c.read(readBuffer);
        //then
        assertEquals(0L, readBuffer.position());
        assertEquals(-1, readCount);
        assertEquals(-1, c.read(readBuffer));
        c.close();
    }

    @Test(expected = ClosedChannelException.class)
    public void shouldThrowExceptionOnReadingClosedChannel() throws IOException {
        //given
        final SeekableInMemoryByteChannel c = new SeekableInMemoryByteChannel();
        //when
        c.close();
        c.read(ByteBuffer.allocate(1));
    }

    @Test
    public void shouldWriteDataProperly() throws IOException {
        //given
        final SeekableInMemoryByteChannel c = new SeekableInMemoryByteChannel();
        final ByteBuffer inData = ByteBuffer.wrap(testData);
        //when
        final int writeCount = c.write(inData);
        //then
        assertEquals(testData.length, writeCount);
        assertArrayEquals(testData, Arrays.copyOf(c.array(), (int) c.size()));
        assertEquals(testData.length, c.position());
        c.close();
    }

    @Test
    public void shouldWriteDataProperlyAfterPositionSet() throws IOException {
        //given
        final SeekableInMemoryByteChannel c = new SeekableInMemoryByteChannel(testData);
        final ByteBuffer inData = ByteBuffer.wrap(testData);
        final ByteBuffer expectedData = ByteBuffer.allocate(testData.length + 5).put(testData, 0, 5).put(testData);
        //when
        c.position(5L);
        final int writeCount = c.write(inData);

        //then
        assertEquals(testData.length, writeCount);
        assertArrayEquals(expectedData.array(), Arrays.copyOf(c.array(), (int) c.size()));
        assertEquals(testData.length + 5, c.position());
        c.close();
    }


    @Test(expected = ClosedChannelException.class)
    public void shouldThrowExceptionOnWritingToClosedChannel() throws IOException {
        //given
        final SeekableInMemoryByteChannel c = new SeekableInMemoryByteChannel();
        //when
        c.close();
        c.write(ByteBuffer.allocate(1));
    }

    @Test
    public void shouldTruncateContentsProperly() {
        //given
        final SeekableInMemoryByteChannel c = new SeekableInMemoryByteChannel(testData);
        //when
        c.truncate(4);
        //then
        final byte[] bytes = Arrays.copyOf(c.array(), (int) c.size());
        assertEquals("Some", new String(bytes, UTF_8));
        c.close();
    }

    @Test
    public void shouldSetProperPositionOnTruncate() throws IOException {
        //given
        final SeekableInMemoryByteChannel c = new SeekableInMemoryByteChannel(testData);
        //when
        c.position(testData.length);
        c.truncate(4L);
        //then
        assertEquals(4L, c.position());
        assertEquals(4L, c.size());
        c.close();
    }

    @Test
    public void shouldSetProperPosition() throws IOException {
        //given
        final SeekableInMemoryByteChannel c = new SeekableInMemoryByteChannel(testData);
        //when
        final long posAtFour = c.position(4L).position();
        final long posAtTheEnd = c.position(testData.length).position();
        final long posPastTheEnd = c.position(testData.length + 1L).position();
        //then
        assertEquals(4L, posAtFour);
        assertEquals(c.size(), posAtTheEnd);
        assertEquals(testData.length + 1L, posPastTheEnd);
        c.close();
    }

    @Test(expected = IOException.class)
    public void shouldThrowExceptionWhenSettingIncorrectPosition() throws IOException {
        //given
        final SeekableInMemoryByteChannel c = new SeekableInMemoryByteChannel();
        //when
        c.position(Integer.MAX_VALUE + 1L);
        c.close();
    }

    @Test(expected = IllegalArgumentException.class)
    public void shouldThrowExceptionWhenTruncatingToIncorrectSize() {
        //given
        final SeekableInMemoryByteChannel c = new SeekableInMemoryByteChannel();
        //when
        c.truncate(Integer.MAX_VALUE + 1L);
        c.close();
    }

    // Contract Tests added in response to https://issues.apache.org/jira/browse/COMPRESS-499

    // https://docs.oracle.com/javase/7/docs/api/java/io/Closeable.html#close()

    /*
     * <q>If the stream is already closed then invoking this method has no effect.</q>
     */
    @Test
    public void closeIsIdempotent() throws Exception {
        try (SeekableByteChannel c = new SeekableInMemoryByteChannel()) {
            c.close();
            assertFalse(c.isOpen());
            c.close();
            assertFalse(c.isOpen());
        }
    }

    // https://docs.oracle.com/javase/7/docs/api/java/nio/channels/SeekableByteChannel.html#position()

    /*
     * <q>ClosedChannelException - If this channel is closed</q>
     */
    @Test(expected = ClosedChannelException.class)
    @Ignore("we deliberately violate the spec")
    public void throwsClosedChannelExceptionWhenPositionIsReadOnClosedChannel() throws Exception {
        try (SeekableByteChannel c = new SeekableInMemoryByteChannel()) {
            c.close();
            c.position();
        }
    }

    // https://docs.oracle.com/javase/7/docs/api/java/nio/channels/SeekableByteChannel.html#size()

    /*
     * <q>ClosedChannelException - If this channel is closed</q>
     */
    @Test(expected = ClosedChannelException.class)
    @Ignore("we deliberately violate the spec")
    public void throwsClosedChannelExceptionWhenSizeIsReadOnClosedChannel() throws Exception {
        try (SeekableByteChannel c = new SeekableInMemoryByteChannel()) {
            c.close();
            c.size();
        }
    }

    // https://docs.oracle.com/javase/7/docs/api/java/nio/channels/SeekableByteChannel.html#position(long)

    /*
     * <q>ClosedChannelException - If this channel is closed</q>
     */
    @Test(expected = ClosedChannelException.class)
    public void throwsClosedChannelExceptionWhenPositionIsSetOnClosedChannel() throws Exception {
        try (SeekableByteChannel c = new SeekableInMemoryByteChannel()) {
            c.close();
            c.position(0);
        }
    }

    /*
     * <q>Setting the position to a value that is greater than the current size is legal but does not change the size of
     * the entity. A later attempt to read bytes at such a position will immediately return an end-of-file
     * indication</q>
     */
    @Test
    public void readingFromAPositionAfterEndReturnsEOF() throws Exception {
        try (SeekableByteChannel c = new SeekableInMemoryByteChannel()) {
            c.position(2);
            assertEquals(2, c.position());
            final ByteBuffer readBuffer = ByteBuffer.allocate(5);
            assertEquals(-1, c.read(readBuffer));
        }
    }

    /*
     * <q>Setting the position to a value that is greater than the current size is legal but does not change the size of
     * the entity. A later attempt to write bytes at such a position will cause the entity to grow to accommodate the
     * new bytes; the values of any bytes between the previous end-of-file and the newly-written bytes are
     * unspecified.</q>
     */
    public void writingToAPositionAfterEndGrowsChannel() throws Exception {
        try (SeekableByteChannel c = new SeekableInMemoryByteChannel()) {
            c.position(2);
            assertEquals(2, c.position());
            final ByteBuffer inData = ByteBuffer.wrap(testData);
            assertEquals(testData.length, c.write(inData));
            assertEquals(testData.length + 2, c.size());

            c.position(2);
            final ByteBuffer readBuffer = ByteBuffer.allocate(testData.length);
            c.read(readBuffer);
            assertArrayEquals(testData, Arrays.copyOf(readBuffer.array(), testData.length));
        }
    }

    /*
     * <q>IOException - If the new position is negative</q>
     */
    @Test(expected = IOException.class)
    public void throwsIOExceptionWhenPositionIsSetToANegativeValue() throws Exception {
        try (SeekableByteChannel c = new SeekableInMemoryByteChannel()) {
            c.position(-1);
        }
    }

    // https://docs.oracle.com/javase/7/docs/api/java/nio/channels/SeekableByteChannel.html#truncate(long)

    /*
     * <q>If the given size is greater than or equal to the current size then the entity is not modified.</q>
     */
    @Test
    public void truncateToCurrentSizeDoesntChangeAnything() throws Exception {
        try (SeekableByteChannel c = new SeekableInMemoryByteChannel(testData)) {
            assertEquals(testData.length, c.size());
            c.truncate(testData.length);
            assertEquals(testData.length, c.size());
            final ByteBuffer readBuffer = ByteBuffer.allocate(testData.length);
            assertEquals(testData.length, c.read(readBuffer));
            assertArrayEquals(testData, Arrays.copyOf(readBuffer.array(), testData.length));
        }
    }

    /*
     * <q>If the given size is greater than or equal to the current size then the entity is not modified.</q>
     */
    @Test
    public void truncateToBiggerSizeDoesntChangeAnything() throws Exception {
        try (SeekableByteChannel c = new SeekableInMemoryByteChannel(testData)) {
            assertEquals(testData.length, c.size());
            c.truncate(testData.length + 1);
            assertEquals(testData.length, c.size());
            final ByteBuffer readBuffer = ByteBuffer.allocate(testData.length);
            assertEquals(testData.length, c.read(readBuffer));
            assertArrayEquals(testData, Arrays.copyOf(readBuffer.array(), testData.length));
        }
    }

    /*
     * <q> In either case, if the current position is greater than the given size then it is set to that size.</q>
     */
    @Test
    public void truncateDoesntChangeSmallPosition() throws Exception {
        try (SeekableByteChannel c = new SeekableInMemoryByteChannel(testData)) {
            c.position(1);
            c.truncate(testData.length - 1);
            assertEquals(testData.length - 1, c.size());
            assertEquals(1, c.position());
        }
    }

    /*
     * <q> In either case, if the current position is greater than the given size then it is set to that size.</q>
     */
    @Test
    public void truncateMovesPositionWhenShrinkingBeyondPosition() throws Exception {
        try (SeekableByteChannel c = new SeekableInMemoryByteChannel(testData)) {
            c.position(4);
            c.truncate(3);
            assertEquals(3, c.size());
            assertEquals(3, c.position());
        }
    }

    /*
     * <q> In either case, if the current position is greater than the given size then it is set to that size.</q>
     */
    @Test
    public void truncateMovesPositionWhenNotResizingButPositionBiggerThanSize() throws Exception {
        try (SeekableByteChannel c = new SeekableInMemoryByteChannel(testData)) {
            c.position(2 * testData.length);
            c.truncate(testData.length);
            assertEquals(testData.length, c.size());
            assertEquals(testData.length, c.position());
        }
    }

    /*
     * <q> In either case, if the current position is greater than the given size then it is set to that size.</q>
     */
    @Test
    public void truncateMovesPositionWhenNewSizeIsBiggerThanSizeAndPositionIsEvenBigger() throws Exception {
        try (SeekableByteChannel c = new SeekableInMemoryByteChannel(testData)) {
            c.position(2 * testData.length);
            c.truncate(testData.length + 1);
            assertEquals(testData.length, c.size());
            assertEquals(testData.length + 1, c.position());
        }
    }

    /*
     * <q>IllegalArgumentException - If the new position is negative</q>
     */
    @Test(expected = IllegalArgumentException.class)
    public void throwsIllegalArgumentExceptionWhenTruncatingToANegativeSize() throws Exception {
        try (SeekableByteChannel c = new SeekableInMemoryByteChannel()) {
            c.truncate(-1);
        }
    }

    /*
     * <q>ClosedChannelException - If this channel is closed</q>
     */
    @Test(expected = ClosedChannelException.class)
    @Ignore("we deliberately violate the spec")
    public void throwsClosedChannelExceptionWhenTruncateIsCalledOnClosedChannel() throws Exception {
        try (SeekableByteChannel c = new SeekableInMemoryByteChannel()) {
            c.close();
            c.truncate(0);
        }
    }

}
