/*
 * 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 android.support.rastermill;

import android.graphics.Bitmap;
import java.nio.ByteBuffer;

import java.io.InputStream;

public class FrameSequence {
    static {
        System.loadLibrary("framesequence");
    }

    private final long mNativeFrameSequence;
    private final int mWidth;
    private final int mHeight;
    private final boolean mOpaque;
    private final int mFrameCount;
    private final int mDefaultLoopCount;

    public int getWidth() { return mWidth; }
    public int getHeight() { return mHeight; }
    public boolean isOpaque() { return mOpaque; }
    public int getFrameCount() { return mFrameCount; }
    public int getDefaultLoopCount() { return mDefaultLoopCount; }

    private static native FrameSequence nativeDecodeByteArray(byte[] data, int offset, int length);
    private static native FrameSequence nativeDecodeStream(InputStream is, byte[] tempStorage);
    private static native FrameSequence nativeDecodeByteBuffer(ByteBuffer buffer, int offset, int capacity);
    private static native void nativeDestroyFrameSequence(long nativeFrameSequence);
    private static native long nativeCreateState(long nativeFrameSequence);
    private static native void nativeDestroyState(long nativeState);
    private static native long nativeGetFrame(long nativeState, int frameNr,
            Bitmap output, int previousFrameNr);

    @SuppressWarnings("unused") // called by native
    private FrameSequence(long nativeFrameSequence, int width, int height,
                          boolean opaque, int frameCount, int defaultLoopCount) {
        mNativeFrameSequence = nativeFrameSequence;
        mWidth = width;
        mHeight = height;
        mOpaque = opaque;
        mFrameCount = frameCount;
        mDefaultLoopCount = defaultLoopCount;
    }

    public static FrameSequence decodeByteArray(byte[] data) {
        return decodeByteArray(data, 0, data.length);
    }

    public static FrameSequence decodeByteArray(byte[] data, int offset, int length) {
        if (data == null) throw new IllegalArgumentException();
        if (offset < 0 || length < 0 || (offset + length > data.length)) {
            throw new IllegalArgumentException("invalid offset/length parameters");
        }
        return nativeDecodeByteArray(data, offset, length);
    }

    public static FrameSequence decodeByteBuffer(ByteBuffer buffer) {
        if (buffer == null) throw new IllegalArgumentException();
        if (!buffer.isDirect()) {
            if (buffer.hasArray()) {
                byte[] byteArray = buffer.array();
                return decodeByteArray(byteArray, buffer.position(), buffer.remaining());
            } else {
                throw new IllegalArgumentException("Cannot have non-direct ByteBuffer with no byte array");
            }
        }
        return nativeDecodeByteBuffer(buffer, buffer.position(), buffer.remaining());
    }

    public static FrameSequence decodeStream(InputStream stream) {
        if (stream == null) throw new IllegalArgumentException();
        byte[] tempStorage = new byte[16 * 1024]; // TODO: use buffer pool
        return nativeDecodeStream(stream, tempStorage);
    }

    State createState() {
        if (mNativeFrameSequence == 0) {
            throw new IllegalStateException("attempted to use incorrectly built FrameSequence");
        }

        long nativeState = nativeCreateState(mNativeFrameSequence);
        if (nativeState == 0) {
            return null;
        }
        return new State(nativeState);
    }

    @Override
    protected void finalize() throws Throwable {
        try {
            if (mNativeFrameSequence != 0) nativeDestroyFrameSequence(mNativeFrameSequence);
        } finally {
            super.finalize();
        }
    }

    /**
     * Playback state used when moving frames forward in a frame sequence.
     *
     * Note that this doesn't require contiguous frames to be rendered, it just stores
     * information (in the case of gif, a recall buffer) that will be used to construct
     * frames based upon data recorded before previousFrameNr.
     *
     * Note: {@link #destroy()} *must* be called before the object is GC'd to free native resources
     *
     * Note: State holds a native ref to its FrameSequence instance, so its FrameSequence should
     * remain ref'd while it is in use
     */
    static class State {
        private long mNativeState;

        public State(long nativeState) {
            mNativeState = nativeState;
        }

        public void destroy() {
            if (mNativeState != 0) {
                nativeDestroyState(mNativeState);
                mNativeState = 0;
            }
        }

        // TODO: consider adding alternate API for drawing into a SurfaceTexture
        public long getFrame(int frameNr, Bitmap output, int previousFrameNr) {
            if (output == null || output.getConfig() != Bitmap.Config.ARGB_8888) {
                throw new IllegalArgumentException("Bitmap passed must be non-null and ARGB_8888");
            }
            if (mNativeState == 0) {
                throw new IllegalStateException("attempted to draw destroyed FrameSequenceState");
            }
            return nativeGetFrame(mNativeState, frameNr, output, previousFrameNr);
        }
    }
}
