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

import static org.junit.jupiter.api.Assertions.assertArrayEquals;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.EOFException;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PushbackInputStream;
import java.nio.ByteBuffer;
import java.nio.channels.ReadableByteChannel;
import java.nio.charset.StandardCharsets;
import java.util.Random;

import org.apache.poi.EmptyFileException;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;

final class TestIOUtils {
    private static File TMP;
    private static final long LENGTH = 300 + new Random().nextInt(9000);

    @BeforeAll
    public static void setUp() throws IOException {
        TMP = File.createTempFile("poi-ioutils-", "");
        try (OutputStream os = new FileOutputStream(TMP)) {
            for (int i = 0; i < LENGTH; i++) {
                os.write(0x01);
            }
        }
    }

    @AfterAll
    public static void tearDown() {
        if (TMP != null) {
            assertTrue(TMP.delete());
        }
    }

    private static InputStream data123() {
        return new ByteArrayInputStream(new byte[]{1,2,3});
    }

    @Test
    void testPeekFirst8Bytes() throws Exception {
        assertArrayEquals("01234567".getBytes(StandardCharsets.UTF_8),
                IOUtils.peekFirst8Bytes(new ByteArrayInputStream("0123456789".getBytes(StandardCharsets.UTF_8))));
    }

    @Test
    void testPeekFirst8BytesWithPushbackInputStream() throws Exception {
        assertArrayEquals("01234567".getBytes(StandardCharsets.UTF_8),
                IOUtils.peekFirst8Bytes(new PushbackInputStream(new ByteArrayInputStream("0123456789".getBytes(StandardCharsets.UTF_8)), 8)));
    }

    @Test
    void testPeekFirst8BytesTooLessAvailable() throws Exception {
        assertArrayEquals(new byte[] { 1, 2, 3, 0, 0, 0, 0, 0}, IOUtils.peekFirst8Bytes(data123()));
    }

    @Test
    void testPeekFirst8BytesEmpty() {
        assertThrows(EmptyFileException.class, () ->
            IOUtils.peekFirst8Bytes(new ByteArrayInputStream(new byte[0])));
    }

    @Test
    void testToByteArray() throws Exception {
        assertArrayEquals(new byte[] { 1, 2, 3}, IOUtils.toByteArray(data123()));
    }

    @Test
    void testToByteArrayToSmall() {
        assertThrows(IOException.class, () -> IOUtils.toByteArray(data123(), 10));
    }

    @Test
    void testToByteArrayMaxLengthToSmall() {
        assertThrows(IOException.class, () -> IOUtils.toByteArray(data123(), 10, 10));
    }

    @Test
    void testToByteArrayNegativeLength() {
        assertThrows(RecordFormatException.class, () -> IOUtils.toByteArray(data123(), -1));
    }

    @Test
    void testToByteArrayNegativeMaxLength() {
        assertThrows(RecordFormatException.class,  () -> IOUtils.toByteArray(data123(), 10, -1));
    }

    @Test
    void testToByteArrayByteBuffer() {
        assertArrayEquals(new byte[] { 1, 2, 3},
                IOUtils.toByteArray(ByteBuffer.wrap(new byte[]{1, 2, 3}), 10));
    }

    @Test
    void testToByteArrayByteBufferNonArray() {
        ByteBuffer buffer = ByteBuffer.allocate(3);
        buffer.put(new byte[] { 1, 2, 3});
        buffer.position(0);
        assertFalse(buffer.asReadOnlyBuffer().hasArray());
        assertEquals(3, buffer.asReadOnlyBuffer().remaining());

        assertArrayEquals(new byte[] { 1, 2, 3},
                IOUtils.toByteArray(buffer.asReadOnlyBuffer(), 3));
    }

    @Test
    void testToByteArrayByteBufferToSmall() {
        assertArrayEquals(new byte[] { 1, 2, 3, 4, 5, 6, 7},
                IOUtils.toByteArray(ByteBuffer.wrap(new byte[]{1, 2, 3, 4, 5, 6, 7}), 3));
    }

    @Test
    void testSkipFully() throws IOException {
        try (InputStream is =  new FileInputStream(TMP)) {
            long skipped = IOUtils.skipFully(is, 20000L);
            assertEquals(LENGTH, skipped);
        }
    }

    @Test
    void testSkipFullyGtIntMax() throws IOException {
        try (InputStream is =  new FileInputStream(TMP)) {
            long skipped = IOUtils.skipFully(is, Integer.MAX_VALUE + 20000L);
            assertEquals(LENGTH, skipped);
        }
    }

    @Test
    void testSkipFullyByteArray() throws IOException {
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        try (InputStream is = new FileInputStream(TMP)) {
            assertEquals(LENGTH, IOUtils.copy(is, bos));
            long skipped = IOUtils.skipFully(new ByteArrayInputStream(bos.toByteArray()), 20000L);
            assertEquals(LENGTH, skipped);
        }
    }

    @Test
    void testSkipFullyByteArrayGtIntMax() throws IOException {
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        try (InputStream is = new FileInputStream(TMP)) {
            assertEquals(LENGTH, IOUtils.copy(is, bos));
            long skipped = IOUtils.skipFully(new ByteArrayInputStream(bos.toByteArray()), Integer.MAX_VALUE + 20000L);
            assertEquals(LENGTH, skipped);
        }
    }

    @Test
    void testCopyToFile() throws IOException {
        File dest = File.createTempFile("poi-ioutils-", "");
        try {
            try (InputStream is = new FileInputStream(TMP)) {
                assertEquals(LENGTH, IOUtils.copy(is, dest));
            }

            try (FileInputStream strOrig = new FileInputStream(TMP);
                FileInputStream strDest = new FileInputStream(dest)) {
                byte[] bytesOrig = new byte[(int)LENGTH];
                byte[] bytesDest = new byte[(int)LENGTH];
                IOUtils.readFully(strOrig, bytesOrig);
                IOUtils.readFully(strDest, bytesDest);
                assertArrayEquals(bytesOrig, bytesDest);
            }
        } finally {
            assertTrue(dest.delete());
        }
    }

    @Test
    void testCopyToInvalidFile() throws IOException {
        try (InputStream is = new FileInputStream(TMP)) {
            assertThrows(RuntimeException.class,
                    () -> IOUtils.copy(is, new File("/notexisting/directory/structure")));
        }
    }

    @Test
    void testSkipFullyBug61294() throws IOException {
        long skipped = IOUtils.skipFully(new ByteArrayInputStream(new byte[0]), 1);
        assertEquals(-1L, skipped);
    }

    @Test
    void testZeroByte() throws IOException {
        long skipped = IOUtils.skipFully((new ByteArrayInputStream(new byte[0])), 100);
        assertEquals(-1L, skipped);
    }

    @Test
    void testSkipZero() throws IOException {
        try (InputStream is =  new FileInputStream(TMP)) {
            long skipped = IOUtils.skipFully(is, 0);
            assertEquals(0, skipped);
        }
    }

    @Test
    void testSkipNegative() throws IOException {
        try (InputStream is =  new FileInputStream(TMP)) {
            assertThrows(IllegalArgumentException.class, () -> IOUtils.skipFully(is, -1));
        }
    }

    @Test
    void testMaxLengthTooLong() throws IOException {
        try (InputStream is = new FileInputStream(TMP)) {
            assertThrows(RecordFormatException.class, () -> IOUtils.toByteArray(is, Integer.MAX_VALUE, 100));
        }
    }

    @Test
    void testMaxLengthIgnored() throws IOException {
        try (InputStream is = new FileInputStream(TMP)) {
            int len = IOUtils.toByteArray(is, 90, Integer.MAX_VALUE).length;
            assertEquals(90, len);
            len = IOUtils.toByteArray(is, 90, 100).length;
            assertEquals(90, len);
            len = IOUtils.toByteArray(is, Integer.MAX_VALUE, Integer.MAX_VALUE).length;
            assertTrue(len > 300-2*90);
        }
    }

    @Test
    void testMaxLengthInvalid() throws IOException {
        try (InputStream is = new FileInputStream(TMP)) {
            assertThrows(RecordFormatException.class, () -> IOUtils.toByteArray(is, 90, 80));
        }
    }

    @Test
    void testWonkyInputStream() throws IOException {
        long skipped = IOUtils.skipFully(new WonkyInputStream(), 10000);
        assertEquals(10000, skipped);
    }

    @Test
    void testSetMaxOverride() throws IOException {
        ByteArrayInputStream stream = new ByteArrayInputStream("abc".getBytes(StandardCharsets.UTF_8));
        byte[] bytes = IOUtils.toByteArray(stream);
        assertNotNull(bytes);
        assertEquals("abc", new String(bytes, StandardCharsets.UTF_8));
    }

    @Test
    void testSetMaxOverrideLimit() throws IOException {
        IOUtils.setByteArrayMaxOverride(30 * 1024 * 1024);
        try {
            ByteArrayInputStream stream = new ByteArrayInputStream("abc".getBytes(StandardCharsets.UTF_8));
            byte[] bytes = IOUtils.toByteArray(stream);
            assertNotNull(bytes);
            assertEquals("abc", new String(bytes, StandardCharsets.UTF_8));
        } finally {
            IOUtils.setByteArrayMaxOverride(-1);
        }
    }

    @Test
    void testSetMaxOverrideOverLimit() {
        IOUtils.setByteArrayMaxOverride(2);
        try {
            ByteArrayInputStream stream = new ByteArrayInputStream("abc".getBytes(StandardCharsets.UTF_8));
            assertThrows(RecordFormatException.class, () -> IOUtils.toByteArray(stream));
        } finally {
            IOUtils.setByteArrayMaxOverride(-1);
        }
    }

    @Test
    void testSetMaxOverrideWithLength() throws IOException {
        ByteArrayInputStream stream = new ByteArrayInputStream("abc".getBytes(StandardCharsets.UTF_8));
        byte[] bytes = IOUtils.toByteArray(stream, 3, 100);
        assertNotNull(bytes);
        assertEquals("abc", new String(bytes, StandardCharsets.UTF_8));
    }

    @Test
    void testSetMaxOverrideLimitWithLength() throws IOException {
        IOUtils.setByteArrayMaxOverride(30 * 1024 * 1024);
        try {
            ByteArrayInputStream stream = new ByteArrayInputStream("abc".getBytes(StandardCharsets.UTF_8));
            byte[] bytes = IOUtils.toByteArray(stream, 3, 100);
            assertNotNull(bytes);
            assertEquals("abc", new String(bytes, StandardCharsets.UTF_8));
        } finally {
            IOUtils.setByteArrayMaxOverride(-1);
        }
    }

    @Test
    void testSetMaxOverrideOverLimitWithLength() {
        IOUtils.setByteArrayMaxOverride(2);
        try {
            ByteArrayInputStream stream = new ByteArrayInputStream("abc".getBytes(StandardCharsets.UTF_8));
            assertThrows(RecordFormatException.class, () -> IOUtils.toByteArray(stream, 3, 100));
        } finally {
            IOUtils.setByteArrayMaxOverride(-1);
        }
    }

    @Test
    void testSafelyAllocate() {
        byte[] bytes = IOUtils.safelyAllocate(30, 200);
        assertNotNull(bytes);
        assertEquals(30, bytes.length);
    }

    @Test
    void testSafelyAllocateLimit() {
        IOUtils.setByteArrayMaxOverride(40);
        try {
            byte[] bytes = IOUtils.safelyAllocate(30, 200);
            assertNotNull(bytes);
            assertEquals(30, bytes.length);
        } finally {
            IOUtils.setByteArrayMaxOverride(-1);
        }
    }

    @Test
    void testReadFully() throws IOException {
        byte[] bytes = new byte[2];
        assertEquals(2, IOUtils.readFully(new ByteArrayInputStream(new byte[] {1, 2, 3}), bytes, 0, 2));
        assertArrayEquals(new byte[] {1,2}, bytes);
    }

    @Test
    void testReadFullyEOF() throws IOException {
        byte[] bytes = new byte[2];
        assertEquals(2, IOUtils.readFully(new NullInputStream(2), bytes, 0, 4));
        assertArrayEquals(new byte[] {0,0}, bytes);
    }

    @Test
    void testReadFullyEOFZero() throws IOException {
        byte[] bytes = new byte[2];
        assertEquals(-1, IOUtils.readFully(new NullInputStream(0), bytes, 0, 4));
        assertArrayEquals(new byte[] {0,0}, bytes);
    }

    @Test
    void testReadFullySimple() throws IOException {
        byte[] bytes = new byte[2];
        assertEquals(2, IOUtils.readFully(new ByteArrayInputStream(new byte[] {1, 2, 3}), bytes));
        assertArrayEquals(new byte[] {1,2}, bytes);
    }

    @Test
    void testReadFullyOffset() throws IOException {
        byte[] bytes = new byte[3];
        assertEquals(2, IOUtils.readFully(new ByteArrayInputStream(new byte[] {1, 2, 3}), bytes, 1, 2));
        assertArrayEquals(new byte[] {0, 1,2}, bytes);
    }

    @Test
    void testReadFullyAtLength() throws IOException {
        byte[] bytes = new byte[3];
        assertEquals(3, IOUtils.readFully(new ByteArrayInputStream(new byte[] {1, 2, 3}), bytes, 0, 3));
        assertArrayEquals(new byte[] {1,2, 3}, bytes);
    }


    @Test
    void testReadFullyChannel() throws IOException {
        ByteBuffer bytes = ByteBuffer.allocate(2);
        assertEquals(2, IOUtils.readFully(new SimpleByteChannel(new byte[]{1, 2, 3}), bytes));
        assertArrayEquals(new byte[] {1,2}, bytes.array());
        assertEquals(2, bytes.position());
    }

    @Test
    void testReadFullyChannelEOF() throws IOException {
        ByteBuffer bytes = ByteBuffer.allocate(2);
        assertEquals(-1, IOUtils.readFully(new EOFByteChannel(false), bytes));
        assertArrayEquals(new byte[] {0,0}, bytes.array());
        assertEquals(0, bytes.position());
    }

    @Test
    void testReadFullyChannelEOFException() {
        ByteBuffer bytes = ByteBuffer.allocate(2);
        assertThrows(IOException.class,
                () -> IOUtils.readFully(new EOFByteChannel(true), bytes));
    }

    @Test
    void testReadFullyChannelSimple() throws IOException {
        ByteBuffer bytes = ByteBuffer.allocate(2);
        assertEquals(2, IOUtils.readFully(new SimpleByteChannel(new byte[] {1, 2, 3}), bytes));
        assertArrayEquals(new byte[] {1,2}, bytes.array());
        assertEquals(2, bytes.position());
    }

    @Test
    public void testChecksum() {
        assertEquals(0L, IOUtils.calculateChecksum(new byte[0]));
        assertEquals(3057449933L, IOUtils.calculateChecksum(new byte[] { 1, 2, 3, 4}));
    }

    @Test
    public void testChecksumStream() throws IOException {
        assertEquals(0L, IOUtils.calculateChecksum(new NullInputStream(0)));
        assertEquals(0L, IOUtils.calculateChecksum(new NullInputStream(1)));
        assertEquals(3057449933L, IOUtils.calculateChecksum(new ByteArrayInputStream(new byte[] { 1, 2, 3, 4})));
        assertThrows(EOFException.class,
                () -> IOUtils.calculateChecksum(new NullInputStream(1, true)));
    }

    /**
     * This returns 0 for the first call to skip and then reads
     * as requested.  This tests that the fallback to read() works.
     */
    private static class WonkyInputStream extends InputStream {
        int skipCalled;
        int readCalled;

        @Override
        public int read() {
            readCalled++;
            return 0;
        }

        @Override
        public int read(byte[] arr, int offset, int len) {
            readCalled++;
            return len;
        }

        @Override
        public long skip(long len) {
            skipCalled++;
            if (skipCalled == 1) {
                return 0;
            } else if (skipCalled > 100) {
                return len;
            } else {
                return 100;
            }
        }

        @Override
        public int available() {
            return 100000;
        }
    }

    private static class EOFByteChannel implements ReadableByteChannel {
        private final boolean throwException;

        public EOFByteChannel(boolean throwException) {
            this.throwException = throwException;
        }

        @Override
        public int read(ByteBuffer dst) throws IOException {
            if (throwException) {
                throw new IOException("EOF");
            }

            return -1;
        }

        @Override
        public boolean isOpen() {
            return false;
        }

        @Override
        public void close() throws IOException {

        }
    }

    private static class SimpleByteChannel extends InputStream implements ReadableByteChannel {
        private final byte[] bytes;

        public SimpleByteChannel(byte[] bytes) {
            this.bytes = bytes;
        }

        @Override
        public int read() throws IOException {
            throw new UnsupportedOperationException();
        }

        @Override
        public int read(ByteBuffer dst) throws IOException {
            int toRead = Math.min(bytes.length, dst.capacity());
            dst.put(bytes, 0, toRead);
            return toRead;
        }

        @Override
        public boolean isOpen() {
            return false;
        }
    }

    public class NullInputStream extends InputStream {
        private final int bytes;
        private final boolean exception;

        private int position;

        public NullInputStream(int bytes) {
            this(bytes, false);
        }

        public NullInputStream(int bytes, boolean exception) {
            this.bytes = bytes;
            this.exception = exception;
        }

        @Override
        public int read() throws IOException {
            if (position >= bytes) {
                return handleReturn();
            }

            position++;
            return 0;
        }

        private int handleReturn() throws EOFException {
            if (exception) {
                throw new EOFException();
            } else {
                return -1;
            }
        }

        @Override
        public int read(byte[] b, int off, int len) throws IOException {
            int toRead = Math.min(b.length, len);
            if (toRead > (bytes - position)) {
                return handleReturn();
            }
            toRead = Math.min(toRead, (bytes - position));

            position += toRead;
            return toRead;
        }
    }
}
