/*
 * Copyright (C) 2013 The Android Open Source Project
 *
 * Licensed 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 com.android.ex.photo.util;

import android.util.Log;

import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;

/**
 * Wrapper for {@link InputStream} that allows you to read bytes from it like a byte[]. An
 * internal buffer is kept as small as possible to avoid large unnecessary allocations.
 *
 * <p/>
 * Care must be taken so that the internal buffer is kept small. The best practice is to
 * precalculate the maximum buffer size that you will need. For example,
 * say you have a loop that reads bytes from index <code>0</code> to <code>10</code>,
 * skips to index <code>N</code>, reads from index <code>N</code> to <code>N+10</code>, etc. Then
 * you know that the internal buffer can have a maximum size of <code>10</code>,
 * and you should set the <code>bufferSize</code> parameter to <code>10</code> in the constructor.
 *
 * <p/>
 * Use {@link #advanceTo(int)} to declare that you will not need to access lesser indexes. This
 * helps to keep the internal buffer small. In the above example, after reading bytes from index
 * <code>0</code> to <code>10</code>, you should call <code>advanceTo(N)</code> so that internal
 * buffer becomes filled with bytes from index <code>N</code> to <code>N+10</code>.
 *
 * <p/>
 * If you know that you are reading bytes from a <strong>strictly</strong> increasing or equal
 * index, then you should set the <code>autoAdvance</code> parameter to <code>true</code> in the
 * constructor. For complicated access patterns, or when you prefer to control the internal
 * buffer yourself, set <code>autoAdvance</code> to <code>false</code>. When
 * <code>autoAdvance</code> is enabled, every time an index is beyond the buffer length,
 * the buffer will be shifted forward such that the index requested becomes the first element in
 * the buffer.
 *
 * <p/>
 * All public methods with parameter <code>index</code> are absolute indexed. The index is from
 * the beginning of the wrapped input stream.
 */
public class InputStreamBuffer {

    private static final boolean DEBUG = false;
    private static final int DEBUG_MAX_BUFFER_SIZE = 80;
    private static final String TAG = "InputStreamBuffer";

    private InputStream mInputStream;
    private byte[] mBuffer;
    private boolean mAutoAdvance;
    /** Byte count the buffer is offset by. */
    private int mOffset = 0;
    /** Number of bytes filled in the buffer. */
    private int mFilled = 0;

    /**
     * Construct a new wrapper for an InputStream.
     *
     * <p/>
     * If <code>autoAdvance</code> is true, behavior is undefined if you call {@link #get(int)}
     * or {@link #has(int)} with an index N, then some arbitrary time later call {@link #get(int)}
     * or {@link #has(int)} with an index M < N. The wrapper may return the right value,
     * if the buffer happens to still contain index M, but more likely it will throw an
     * {@link IllegalStateException}.
     *
     * <p/>
     * If <code>autoAdvance</code> is false, you must be diligent and call {@link #advanceTo(int)}
     * at the appropriate times to ensure that the internal buffer is not unnecessarily resized
     * and reallocated.
     *
     * @param inputStream The input stream to wrap. The input stream will not be closed by the
     *                    wrapper.
     * @param bufferSize  The initial size for the internal buffer. The buffer size should be
     *                    carefully chosen to avoid resizing and reallocating the internal buffer.
     *                    The internal buffer size used will be the least power of two greater
     *                    than this parameter.
     * @param autoAdvance Determines the behavior when you need to read an index that is beyond
     *                    the internal buffer size. If true, the internal buffer will shift so
     *                    that the requested index becomes the first element. If false,
     *                    the internal buffer size will grow to the smallest power of 2 which is
     *                    greater than the requested index.
     */
    public InputStreamBuffer(final InputStream inputStream, int bufferSize,
            final boolean autoAdvance) {
        mInputStream = inputStream;
        if (bufferSize <= 0) {
            throw new IllegalArgumentException(
                    String.format("Buffer size %d must be positive.", bufferSize));
        }
        bufferSize = leastPowerOf2(bufferSize);
        mBuffer = new byte[bufferSize];
        mAutoAdvance = autoAdvance;
    }

    /**
     * Attempt to get byte at the requested index from the wrapped input stream. If the internal
     * buffer contains the requested index, return immediately. If the index is less than the
     * head of the buffer, or the index is greater or equal to the size of the wrapped input stream,
     * a runtime exception is thrown.
     *
     * <p/>
     * If the index is not in the internal buffer, but it can be requested from the input stream,
     * {@link #fill(int)} will be called first, and the byte at the index returned.
     *
     * <p/>
     * You should always call {@link #has(int)} with the same index, unless you are sure that no
     * exceptions will be thrown as described above.
     *
     * <p/>
     * Consider calling {@link #advanceTo(int)} if you know that you will never request a lesser
     * index in the future.
     * @param index The requested index.
     * @return The byte at that index.
     */
    public byte get(final int index) throws IllegalStateException, IndexOutOfBoundsException {
        Trace.beginSection("get");
        if (has(index)) {
            final int i = index - mOffset;
            Trace.endSection();
            return mBuffer[i];
        } else {
            Trace.endSection();
            throw new IndexOutOfBoundsException(
                    String.format("Index %d beyond length.", index));
        }
    }

    /**
     * Attempt to return whether the requested index is within the size of the wrapped input
     * stream. One side effect is {@link #fill(int)} will be called.
     *
     * <p/>
     * If this method returns true, it is guaranteed that {@link #get(int)} with the same index
     * will not fail. That means that if the requested index is within the size of the wrapped
     * input stream, but the index is less than the head of the internal buffer,
     * a runtime exception is thrown.
     *
     * <p/>
     * See {@link #get(int)} for caveats. A lot of the same warnings about exceptions and
     * <code>advanceTo()</code> apply.
     * @param index The requested index.
     * @return True if requested index is within the size of the wrapped input stream. False if
     * the index is beyond the size.
     */
    public boolean has(final int index) throws IllegalStateException, IndexOutOfBoundsException {
        Trace.beginSection("has");
        if (index < mOffset) {
            Trace.endSection();
            throw new IllegalStateException(
                    String.format("Index %d is before buffer %d", index, mOffset));
        }

        final int i = index - mOffset;

        // Requested index not in internal buffer.
        if (i >= mFilled || i >= mBuffer.length) {
            Trace.endSection();
            return fill(index);
        }

        Trace.endSection();
        return true;
    }

    /**
     * Attempts to advance the head of the buffer to the requested index. If the index is less
     * than the head of the buffer, the internal state will not be changed.
     *
     * <p/>
     * Advancing does not fill the internal buffer. The next {@link #get(int)} or
     * {@link #has(int)} call will fill the buffer.
     */
    public void advanceTo(final int index) throws IllegalStateException, IndexOutOfBoundsException {
        Trace.beginSection("advance to");
        final int i = index - mOffset;
        if (i <= 0) {
            // noop
            Trace.endSection();
            return;
        } else if (i < mFilled) {
            // Shift elements starting at i to position 0.
            shiftToBeginning(i);
            mOffset = index;
            mFilled = mFilled - i;
        } else if (mInputStream != null) {
            // Burn some bytes from the input stream to match the new index.
            int burn = i - mFilled;
            boolean empty = false;
            int fails = 0;
            try {
                while (burn > 0) {
                    final long burned = mInputStream.skip(burn);
                    if (burned <= 0) {
                        fails++;
                    } else {
                        burn -= burned;
                    }

                    if (fails >= 5) {
                        empty = true;
                        break;
                    }
                }
            } catch (IOException ignored) {
                empty = true;
            }

            if (empty) {
                //Mark input stream as consumed.
                mInputStream = null;
            }

            mOffset = index - burn;
            mFilled = 0;
        } else {
            // Advancing beyond the input stream.
            mOffset = index;
            mFilled = 0;
        }

        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, String.format("advanceTo %d buffer: %s", i, this));
        }
        Trace.endSection();
    }

    /**
     * Attempt to fill the internal buffer fully. The buffer will be modified such that the
     * requested index will always be in the buffer. If the index is less
     * than the head of the buffer, a runtime exception is thrown.
     *
     * <p/>
     * If the requested index is already in bounds of the buffer, then the buffer will just be
     * filled.
     *
     * <p/>
     * Otherwise, if <code>autoAdvance</code> was set to true in the constructor,
     * {@link #advanceTo(int)} will be called with the requested index,
     * and then the buffer filled. If <code>autoAdvance</code> was set to false,
     * we allocate a single larger buffer of a least multiple-of-two size that can contain the
     * requested index. The elements in the old buffer are copied over to the head of the new
     * buffer. Then the entire buffer is filled.
     * @param index The requested index.
     * @return True if the byte at the requested index has been filled. False if the wrapped
     * input stream ends before we reach the index.
     */
    private boolean fill(final int index) {
        Trace.beginSection("fill");
        if (index < mOffset) {
            Trace.endSection();
            throw new IllegalStateException(
                    String.format("Index %d is before buffer %d", index, mOffset));
        }

        int i = index - mOffset;
        // Can't fill buffer anymore if input stream is consumed.
        if (mInputStream == null) {
            Trace.endSection();
            return false;
        }

        // Increase buffer size if necessary.
        int length = i + 1;
        if (length > mBuffer.length) {
            if (mAutoAdvance) {
                advanceTo(index);
                i = index - mOffset;
            } else {
                length = leastPowerOf2(length);
                Log.w(TAG, String.format(
                        "Increasing buffer length from %d to %d. Bad buffer size chosen, "
                                + "or advanceTo() not called.",
                        mBuffer.length, length));
                mBuffer = Arrays.copyOf(mBuffer, length);
            }
        }

        // Read from input stream to fill buffer.
        int read = -1;
        try {
            read = mInputStream.read(mBuffer, mFilled, mBuffer.length - mFilled);
        } catch (IOException ignored) {
        }

        if (read != -1) {
            mFilled = mFilled + read;
        } else {
            // Mark input stream as consumed.
            mInputStream = null;
        }

        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, String.format("fill %d      buffer: %s", i, this));
        }

        Trace.endSection();
        return i < mFilled;
    }

    /**
     * Modify the internal buffer so that all the bytes are shifted towards the head by
     * <code>i</code>. In other words, the byte at index <code>i</code> will now be at index
     * <code>0</code>. Bytes from a lesser index are tossed.
     * @param i How much to shift left.
     */
    private void shiftToBeginning(final int i) {
        if (i >= mBuffer.length) {
            throw new IndexOutOfBoundsException(
                    String.format("Index %d out of bounds. Length %d", i, mBuffer.length));
        }
        for (int j = 0; j + i < mFilled; j++) {
            mBuffer[j] = mBuffer[j + i];
        }
    }

    @Override
    public String toString() {
        if (DEBUG) {
            return toDebugString();
        }
        return String.format("+%d+%d [%d]", mOffset, mBuffer.length, mFilled);
    }

    public String toDebugString() {
        Trace.beginSection("to debug string");
        final StringBuilder sb = new StringBuilder();
        sb.append("+").append(mOffset);
        sb.append("+").append(mBuffer.length);
        sb.append(" [");
        for (int i = 0; i < mBuffer.length && i < DEBUG_MAX_BUFFER_SIZE; i++) {
            if (i > 0) {
                sb.append(",");
            }
            if (i < mFilled) {
                sb.append(String.format("%02X", mBuffer[i]));
            } else {
                sb.append("__");
            }
        }
        if (mInputStream != null) {
            sb.append("...");
        }
        sb.append("]");

        Trace.endSection();
        return sb.toString();
    }

    /**
     * Calculate the least power of two greater than or equal to the input.
     */
    private static int leastPowerOf2(int n) {
        n--;
        n |= n >> 1;
        n |= n >> 2;
        n |= n >> 4;
        n |= n >> 8;
        n |= n >> 16;
        n++;
        return n;
    }
}
