/*
 * 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.imaging.common.bytesource;

import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;

public class ByteSourceInputStream extends ByteSource
{
    private final InputStream is;
    private CacheBlock cacheHead = null;
    private static final int BLOCK_SIZE = 1024;

    public ByteSourceInputStream(InputStream is, String filename)
    {
        super(filename);
        this.is = new BufferedInputStream(is);
    }

    private class CacheBlock
    {
        public final byte bytes[];
        private CacheBlock next = null;
        private boolean triedNext = false;

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

        public CacheBlock getNext() throws IOException
        {
            if (null != next)
                return next;
            if (triedNext)
                return null;
            triedNext = true;
            next = readBlock();
            return next;
        }

    }

    private byte readBuffer[] = null;

    private CacheBlock readBlock() throws IOException
    {
        if (null == readBuffer)
            readBuffer = new byte[BLOCK_SIZE];

        int read = is.read(readBuffer);
        if (read < 1)
            return null;
        else if (read < BLOCK_SIZE)
        {
            // return a copy.
            byte result[] = new byte[read];
            System.arraycopy(readBuffer, 0, result, 0, read);
            return new CacheBlock(result);
        }
        else
        {
            // return current buffer.
            byte result[] = readBuffer;
            readBuffer = null;
            return new CacheBlock(result);
        }
    }

    private CacheBlock getFirstBlock() throws IOException
    {
        if (null == cacheHead)
            cacheHead = readBlock();
        return cacheHead;
    }

    private class CacheReadingInputStream extends InputStream
    {
        private CacheBlock block = null;
        private boolean readFirst = false;
        private int blockIndex = 0;

        @Override
        public int read() throws IOException
        {
            if (null == block)
            {
                if (readFirst)
                    return -1;
                block = getFirstBlock();
                readFirst = true;
            }

            if (block != null && blockIndex >= block.bytes.length)
            {
                block = block.getNext();
                blockIndex = 0;
            }

            if (null == block)
                return -1;

            if (blockIndex >= block.bytes.length)
                return -1;

            return 0xff & block.bytes[blockIndex++];
        }

        @Override
        public int read(byte b[], int off, int len) throws IOException
        {
            // first section copied verbatim from InputStream
            if (b == null)
                throw new NullPointerException();
            else if ((off < 0) || (off > b.length) || (len < 0)
                    || ((off + len) > b.length) || ((off + len) < 0))
                throw new IndexOutOfBoundsException();
            else if (len == 0)
                return 0;

            // optimized block read

            if (null == block)
            {
                if (readFirst)
                    return -1;
                block = getFirstBlock();
                readFirst = true;
            }

            if (block != null && blockIndex >= block.bytes.length)
            {
                block = block.getNext();
                blockIndex = 0;
            }

            if (null == block)
                return -1;

            if (blockIndex >= block.bytes.length)
                return -1;

            int readSize = Math.min(len, block.bytes.length - blockIndex);
            System.arraycopy(block.bytes, blockIndex, b, off, readSize);
            blockIndex += readSize;
            return readSize;
        }

    }

    @Override
    public InputStream getInputStream() throws IOException
    {
        return new CacheReadingInputStream();
    }

    @Override
    public byte[] getBlock(int blockStart, int blockLength) throws IOException
    {
        // We include a separate check for int overflow.
        if ((blockStart < 0)
                || (blockLength < 0)
                || (blockStart + blockLength < 0)
                || (blockStart + blockLength > streamLength.longValue())) {
            throw new IOException("Could not read block (block start: " + blockStart
                    + ", block length: " + blockLength + ", data length: "
                    + streamLength + ").");
        }

        InputStream is = getInputStream();
        skipBytes(is, blockStart);

        byte bytes[] = new byte[blockLength];
        int total = 0;
        while (true)
        {
            int read = is.read(bytes, total, bytes.length - total);
            if (read < 1)
                throw new IOException("Could not read block.");
            total += read;
            if (total >= blockLength)
                return bytes;
        }
    }

    private Long streamLength = null;

    @Override
    public long getLength() throws IOException
    {
        if (streamLength != null)
            return streamLength.longValue();

        InputStream is = getInputStream();
        long result = 0;
        long skipped;
        while ((skipped = is.skip(1024)) > 0)
            result += skipped;
        streamLength = result;
        return result;
    }

    @Override
    public byte[] getAll() throws IOException
    {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();

        CacheBlock block = getFirstBlock();
        while (block != null)
        {
            baos.write(block.bytes);
            block = block.getNext();
        }
        return baos.toByteArray();
    }

    @Override
    public String getDescription()
    {
        return "Inputstream: '" + filename + "'";
    }

}