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

import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;

/**
 * An implementation of the RandomAccessRead interface to store data in memory. The data will be stored in chunks
 * organized in an ArrayList.
 */
public class RandomAccessReadBuffer implements RandomAccessRead
{
    // default chunk size is 4kb
    private static final int DEFAULT_CHUNK_SIZE_4KB = 1 << 12;
    // use the default chunk size
    private int chunkSize = DEFAULT_CHUNK_SIZE_4KB;
    // list containing all chunks
    private List<ByteBuffer> bufferList = null;
    // current chunk
    private ByteBuffer currentBuffer;
    // current pointer to the whole buffer
    private long pointer = 0;
    // current pointer for the current chunk
    private int currentBufferPointer = 0;
    // size of the whole buffer
    private long size = 0;
    // current chunk list index
    private int bufferListIndex = 0;
    // maximum chunk list index
    private int bufferListMaxIndex = 0;

    /**
     * Default constructor.
     */
    private RandomAccessReadBuffer()
    {
        this(DEFAULT_CHUNK_SIZE_4KB);
    }

    /**
     * Default constructor.
     */
    private RandomAccessReadBuffer(int definedChunkSize)
    {
        // starting with one chunk
        chunkSize = definedChunkSize;
        currentBuffer = ByteBuffer.allocate(chunkSize);
        bufferList = new ArrayList<>();
        bufferList.add(currentBuffer);
    }

    /**
     * Create a random access buffer using the given byte array.
     * 
     * @param input the byte array to be read
     */
    public RandomAccessReadBuffer(byte[] input)
    {
        // this is a special case. Wrap the given byte array to a single ByteBuffer.
        this(ByteBuffer.wrap(input));
    }

    /**
     * Create a random access buffer using the given ByteBuffer.
     * 
     * @param input the ByteBuffer to be read
     */
    public RandomAccessReadBuffer(ByteBuffer input)
    {
        chunkSize = input.capacity();
        size = chunkSize;
        currentBuffer = input;
        bufferList = new ArrayList<>(1);
        bufferList.add(currentBuffer);
    }

    /**
     * Create a random access read buffer of the given input stream by copying the data.
     * 
     * @param input the input stream to be read
     * @throws IOException if something went wrong while copying the data
     */
    public RandomAccessReadBuffer(InputStream input) throws IOException
    {
        this();
        int bytesRead = 0;
        int remainingBytes = chunkSize;
        int offset = 0;
        byte[] eofCheck = new byte[1];
        while ((bytesRead = input.read(currentBuffer.array(), offset, remainingBytes)) > -1)
        {
            remainingBytes -= bytesRead;
            offset += bytesRead;
            size += bytesRead;
            if (remainingBytes == 0 && input.read(eofCheck) > 0)
            {
                expandBuffer();
                currentBuffer.put(eofCheck);
                offset = 1;
                remainingBytes = chunkSize - 1;
                size++;
            }
        }
        currentBuffer.limit(offset);
        seek(0);
    }

    private RandomAccessReadBuffer(RandomAccessReadBuffer parent)
    {
        chunkSize = parent.chunkSize;
        size = parent.size;
        bufferListMaxIndex = parent.bufferListMaxIndex;
        bufferList = new ArrayList<>(parent.bufferList.size());
        for (ByteBuffer buffer : parent.bufferList)
        {
            ByteBuffer newBuffer = buffer.duplicate();
            newBuffer.rewind();
            bufferList.add(newBuffer);
        }
        currentBuffer = bufferList.get(0);
        
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void close() throws IOException
    {
        currentBuffer = null;
        bufferList.clear();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void seek(long position) throws IOException
    {
        checkClosed();
        if (position < 0)
        {
            throw new IOException("Invalid position " + position);
        }
        if (position < size)
        {
            pointer = position;
            // calculate the chunk list index
            bufferListIndex = chunkSize > 0 ? (int) (pointer / chunkSize) : 0;
            currentBufferPointer = chunkSize > 0 ? (int) (pointer % chunkSize) : 0;
            currentBuffer = bufferList.get(bufferListIndex);
        }
        else
        {
            // it is allowed to jump beyond the end of the file
            // jump to the end of the buffer
            pointer = size;
            bufferListIndex = bufferListMaxIndex;
            currentBuffer = bufferList.get(bufferListIndex);
            currentBufferPointer = chunkSize > 0 ? (int) (size % chunkSize) : 0;
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public long getPosition() throws IOException
    {
        checkClosed();
        return pointer;
    }
    
    /**
     * {@inheritDoc}
     */
    @Override
    public int read() throws IOException
    {
        checkClosed();
        if (pointer >= this.size)
        {
            return -1;
        }
        if (currentBufferPointer >= chunkSize)
        {
            if (bufferListIndex >= bufferListMaxIndex)
            {
                return -1;
            }
            else
            {
                currentBuffer = bufferList.get(++bufferListIndex);
                currentBufferPointer = 0;
            }
        }
        pointer++;
        return currentBuffer.get(currentBufferPointer++) & 0xff;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public int read(byte[] b, int offset, int length) throws IOException
    {
        checkClosed();
        int bytesRead = readRemainingBytes(b, offset, length);
        if (bytesRead == -1)
        {
            return -1;
        }
        while (bytesRead < length && available() > 0)
        {
            if (currentBufferPointer == chunkSize)
            {
                nextBuffer();
            }
            bytesRead += readRemainingBytes(b, offset + bytesRead, length - bytesRead);
        }
        return bytesRead;
    }

    private int readRemainingBytes(byte[] b, int offset, int length)
    {
        if (pointer >= size)
        {
            return -1;
        }
        int maxLength = (int) Math.min(length, size - pointer);
        int remainingBytes = chunkSize - currentBufferPointer;
        // no more bytes left
        if (remainingBytes == 0)
        {
            return -1;
        }
        if (maxLength >= remainingBytes)
        {
            // copy the remaining bytes from the current buffer
            currentBuffer.position(currentBufferPointer);
            currentBuffer.get(b, offset, remainingBytes);
            // end of file reached
            currentBufferPointer += remainingBytes;
            pointer += remainingBytes;
            return remainingBytes;
        }
        else
        {
            // copy the remaining bytes from the whole buffer
            currentBuffer.position(currentBufferPointer);
            currentBuffer.get(b, offset, maxLength);
            // end of file reached
            currentBufferPointer += maxLength;
            pointer += maxLength;
            return maxLength;
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public long length() throws IOException
    {
        checkClosed();
        return size;
    }

    /**
     * create a new buffer chunk and adjust all pointers and indices.
     */
    private void expandBuffer() throws IOException
    {
        if (bufferListMaxIndex > bufferListIndex)
        {
            // there is already an existing chunk
            nextBuffer();
        }
        else
        {
            // create a new chunk and add it to the buffer
            currentBuffer = ByteBuffer.allocate(chunkSize);
            bufferList.add(currentBuffer);
            currentBufferPointer = 0;
            bufferListMaxIndex++;
            bufferListIndex++;
        }
    }

    /**
     * switch to the next buffer chunk and reset the buffer pointer.
     */
    private void nextBuffer() throws IOException
    {
        if (bufferListIndex == bufferListMaxIndex)
        {
            throw new IOException("No more chunks available, end of buffer reached");
        }
        currentBufferPointer = 0;
        currentBuffer = bufferList.get(++bufferListIndex);
    }
    
    /**
     * Ensure that the RandomAccessBuffer is not closed
     * @throws IOException
     */
    private void checkClosed() throws IOException
    {
        if (currentBuffer == null)
        {
            // consider that the rab is closed if there is no current buffer
            throw new IOException("RandomAccessBuffer already closed");
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean isClosed()
    {
        return currentBuffer == null;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean isEOF() throws IOException
    {
        checkClosed();
        return pointer >= size;
    }

    @Override
    public RandomAccessReadView createView(long startPosition, long streamLength) throws IOException
    {
        return new RandomAccessReadView(new RandomAccessReadBuffer(this), startPosition,
                streamLength, true);
    }

}
