/*
 * Copyright (C) 2010 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.gallery3d.ui;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Rect;

import com.android.gallery3d.common.Utils;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;

import javax.microedition.khronos.opengles.GL11;

// NinePatchTexture is a texture backed by a NinePatch resource.
//
// getPaddings() returns paddings specified in the NinePatch.
// getNinePatchChunk() returns the layout data specified in the NinePatch.
//
public class NinePatchTexture extends ResourceTexture {
    @SuppressWarnings("unused")
    private static final String TAG = "NinePatchTexture";
    private NinePatchChunk mChunk;
    private SmallCache<NinePatchInstance> mInstanceCache
            = new SmallCache<NinePatchInstance>();

    public NinePatchTexture(Context context, int resId) {
        super(context, resId);
    }

    @Override
    protected Bitmap onGetBitmap() {
        if (mBitmap != null) return mBitmap;

        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inPreferredConfig = Bitmap.Config.ARGB_8888;
        Bitmap bitmap = BitmapFactory.decodeResource(
                mContext.getResources(), mResId, options);
        mBitmap = bitmap;
        setSize(bitmap.getWidth(), bitmap.getHeight());
        byte[] chunkData = bitmap.getNinePatchChunk();
        mChunk = chunkData == null
                ? null
                : NinePatchChunk.deserialize(bitmap.getNinePatchChunk());
        if (mChunk == null) {
            throw new RuntimeException("invalid nine-patch image: " + mResId);
        }
        return bitmap;
    }

    public Rect getPaddings() {
        // get the paddings from nine patch
        if (mChunk == null) onGetBitmap();
        return mChunk.mPaddings;
    }

    public NinePatchChunk getNinePatchChunk() {
        if (mChunk == null) onGetBitmap();
        return mChunk;
    }

    // This is a simple cache for a small number of things. Linear search
    // is used because the cache is small. It also tries to remove less used
    // item when the cache is full by moving the often-used items to the front.
    private static class SmallCache<V> {
        private static final int CACHE_SIZE = 16;
        private static final int CACHE_SIZE_START_MOVE = CACHE_SIZE / 2;
        private int[] mKey = new int[CACHE_SIZE];
        private V[] mValue = (V[]) new Object[CACHE_SIZE];
        private int mCount;  // number of items in this cache

        // Puts a value into the cache. If the cache is full, also returns
        // a less used item, otherwise returns null.
        public V put(int key, V value) {
            if (mCount == CACHE_SIZE) {
                V old = mValue[CACHE_SIZE - 1];  // remove the last item
                mKey[CACHE_SIZE - 1] = key;
                mValue[CACHE_SIZE - 1] = value;
                return old;
            } else {
                mKey[mCount] = key;
                mValue[mCount] = value;
                mCount++;
                return null;
            }
        }

        public V get(int key) {
            for (int i = 0; i < mCount; i++) {
                if (mKey[i] == key) {
                    // Move the accessed item one position to the front, so it
                    // will less likely to be removed when cache is full. Only
                    // do this if the cache is starting to get full.
                    if (mCount > CACHE_SIZE_START_MOVE && i > 0) {
                        int tmpKey = mKey[i];
                        mKey[i] = mKey[i - 1];
                        mKey[i - 1] = tmpKey;

                        V tmpValue = mValue[i];
                        mValue[i] = mValue[i - 1];
                        mValue[i - 1] = tmpValue;
                    }
                    return mValue[i];
                }
            }
            return null;
        }

        public void clear() {
            for (int i = 0; i < mCount; i++) {
                mValue[i] = null;  // make sure it's can be garbage-collected.
            }
            mCount = 0;
        }

        public int size() {
            return mCount;
        }

        public V valueAt(int i) {
            return mValue[i];
        }
    }

    private NinePatchInstance findInstance(GLCanvas canvas, int w, int h) {
        int key = w;
        key = (key << 16) | h;
        NinePatchInstance instance = mInstanceCache.get(key);

        if (instance == null) {
            instance = new NinePatchInstance(this, w, h);
            NinePatchInstance removed = mInstanceCache.put(key, instance);
            if (removed != null) {
                removed.recycle(canvas);
            }
        }

        return instance;
    }

    @Override
    public void draw(GLCanvas canvas, int x, int y, int w, int h) {
        if (!isLoaded(canvas)) {
            mInstanceCache.clear();
        }

        if (w != 0 && h != 0) {
            findInstance(canvas, w, h).draw(canvas, this, x, y);
        }
    }

    @Override
    public void recycle() {
        super.recycle();
        GLCanvas canvas = mCanvasRef;
        if (canvas == null) return;
        int n = mInstanceCache.size();
        for (int i = 0; i < n; i++) {
            NinePatchInstance instance = mInstanceCache.valueAt(i);
            instance.recycle(canvas);
        }
        mInstanceCache.clear();
    }
}

// This keeps data for a specialization of NinePatchTexture with the size
// (width, height). We pre-compute the coordinates for efficiency.
class NinePatchInstance {

    @SuppressWarnings("unused")
    private static final String TAG = "NinePatchInstance";

    // We need 16 vertices for a normal nine-patch image (the 4x4 vertices)
    private static final int VERTEX_BUFFER_SIZE = 16 * 2;

    // We need 22 indices for a normal nine-patch image, plus 2 for each
    // transparent region. Current there are at most 1 transparent region.
    private static final int INDEX_BUFFER_SIZE = 22 + 2;

    private FloatBuffer mXyBuffer;
    private FloatBuffer mUvBuffer;
    private ByteBuffer mIndexBuffer;

    // Names for buffer names: xy, uv, index.
    private int[] mBufferNames;

    private int mIdxCount;

    public NinePatchInstance(NinePatchTexture tex, int width, int height) {
        NinePatchChunk chunk = tex.getNinePatchChunk();

        if (width <= 0 || height <= 0) {
            throw new RuntimeException("invalid dimension");
        }

        // The code should be easily extended to handle the general cases by
        // allocating more space for buffers. But let's just handle the only
        // use case.
        if (chunk.mDivX.length != 2 || chunk.mDivY.length != 2) {
            throw new RuntimeException("unsupported nine patch");
        }

        float divX[] = new float[4];
        float divY[] = new float[4];
        float divU[] = new float[4];
        float divV[] = new float[4];

        int nx = stretch(divX, divU, chunk.mDivX, tex.getWidth(), width);
        int ny = stretch(divY, divV, chunk.mDivY, tex.getHeight(), height);

        prepareVertexData(divX, divY, divU, divV, nx, ny, chunk.mColor);
    }

    /**
     * Stretches the texture according to the nine-patch rules. It will
     * linearly distribute the strechy parts defined in the nine-patch chunk to
     * the target area.
     *
     * <pre>
     *                      source
     *          /--------------^---------------\
     *         u0    u1       u2  u3     u4   u5
     * div ---> |fffff|ssssssss|fff|ssssss|ffff| ---> u
     *          |    div0    div1 div2   div3  |
     *          |     |       /   /      /    /
     *          |     |      /   /     /    /
     *          |     |     /   /    /    /
     *          |fffff|ssss|fff|sss|ffff| ---> x
     *         x0    x1   x2  x3  x4   x5
     *          \----------v------------/
     *                  target
     *
     * f: fixed segment
     * s: stretchy segment
     * </pre>
     *
     * @param div the stretch parts defined in nine-patch chunk
     * @param source the length of the texture
     * @param target the length on the drawing plan
     * @param u output, the positions of these dividers in the texture
     *        coordinate
     * @param x output, the corresponding position of these dividers on the
     *        drawing plan
     * @return the number of these dividers.
     */
    private static int stretch(
            float x[], float u[], int div[], int source, int target) {
        int textureSize = Utils.nextPowerOf2(source);
        float textureBound = (float) source / textureSize;

        float stretch = 0;
        for (int i = 0, n = div.length; i < n; i += 2) {
            stretch += div[i + 1] - div[i];
        }

        float remaining = target - source + stretch;

        float lastX = 0;
        float lastU = 0;

        x[0] = 0;
        u[0] = 0;
        for (int i = 0, n = div.length; i < n; i += 2) {
            // Make the stretchy segment a little smaller to prevent sampling
            // on neighboring fixed segments.
            // fixed segment
            x[i + 1] = lastX + (div[i] - lastU) + 0.5f;
            u[i + 1] = Math.min((div[i] + 0.5f) / textureSize, textureBound);

            // stretchy segment
            float partU = div[i + 1] - div[i];
            float partX = remaining * partU / stretch;
            remaining -= partX;
            stretch -= partU;

            lastX = x[i + 1] + partX;
            lastU = div[i + 1];
            x[i + 2] = lastX - 0.5f;
            u[i + 2] = Math.min((lastU - 0.5f)/ textureSize, textureBound);
        }
        // the last fixed segment
        x[div.length + 1] = target;
        u[div.length + 1] = textureBound;

        // remove segments with length 0.
        int last = 0;
        for (int i = 1, n = div.length + 2; i < n; ++i) {
            if ((x[i] - x[last]) < 1f) continue;
            x[++last] = x[i];
            u[last] = u[i];
        }
        return last + 1;
    }

    private void prepareVertexData(float x[], float y[], float u[], float v[],
            int nx, int ny, int[] color) {
        /*
         * Given a 3x3 nine-patch image, the vertex order is defined as the
         * following graph:
         *
         * (0) (1) (2) (3)
         *  |  /|  /|  /|
         *  | / | / | / |
         * (4) (5) (6) (7)
         *  | \ | \ | \ |
         *  |  \|  \|  \|
         * (8) (9) (A) (B)
         *  |  /|  /|  /|
         *  | / | / | / |
         * (C) (D) (E) (F)
         *
         * And we draw the triangle strip in the following index order:
         *
         * index: 04152637B6A5948C9DAEBF
         */
        int pntCount = 0;
        float xy[] = new float[VERTEX_BUFFER_SIZE];
        float uv[] = new float[VERTEX_BUFFER_SIZE];
        for (int j = 0; j < ny; ++j) {
            for (int i = 0; i < nx; ++i) {
                int xIndex = (pntCount++) << 1;
                int yIndex = xIndex + 1;
                xy[xIndex] = x[i];
                xy[yIndex] = y[j];
                uv[xIndex] = u[i];
                uv[yIndex] = v[j];
            }
        }

        int idxCount = 1;
        boolean isForward = false;
        byte index[] = new byte[INDEX_BUFFER_SIZE];
        for (int row = 0; row < ny - 1; row++) {
            --idxCount;
            isForward = !isForward;

            int start, end, inc;
            if (isForward) {
                start = 0;
                end = nx;
                inc = 1;
            } else {
                start = nx - 1;
                end = -1;
                inc = -1;
            }

            for (int col = start; col != end; col += inc) {
                int k = row * nx + col;
                if (col != start) {
                    int colorIdx = row * (nx - 1) + col;
                    if (isForward) colorIdx--;
                    if (color[colorIdx] == NinePatchChunk.TRANSPARENT_COLOR) {
                        index[idxCount] = index[idxCount - 1];
                        ++idxCount;
                        index[idxCount++] = (byte) k;
                    }
                }

                index[idxCount++] = (byte) k;
                index[idxCount++] = (byte) (k + nx);
            }
        }

        mIdxCount = idxCount;

        int size = (pntCount * 2) * (Float.SIZE / Byte.SIZE);
        mXyBuffer = allocateDirectNativeOrderBuffer(size).asFloatBuffer();
        mUvBuffer = allocateDirectNativeOrderBuffer(size).asFloatBuffer();
        mIndexBuffer = allocateDirectNativeOrderBuffer(mIdxCount);

        mXyBuffer.put(xy, 0, pntCount * 2).position(0);
        mUvBuffer.put(uv, 0, pntCount * 2).position(0);
        mIndexBuffer.put(index, 0, idxCount).position(0);
    }

    private static ByteBuffer allocateDirectNativeOrderBuffer(int size) {
        return ByteBuffer.allocateDirect(size).order(ByteOrder.nativeOrder());
    }

    private void prepareBuffers(GLCanvas canvas) {
        mBufferNames = new int[3];
        GL11 gl = canvas.getGLInstance();
        gl.glGenBuffers(3, mBufferNames, 0);

        gl.glBindBuffer(GL11.GL_ARRAY_BUFFER, mBufferNames[0]);
        gl.glBufferData(GL11.GL_ARRAY_BUFFER,
                mXyBuffer.capacity() * (Float.SIZE / Byte.SIZE),
                mXyBuffer, GL11.GL_STATIC_DRAW);

        gl.glBindBuffer(GL11.GL_ARRAY_BUFFER, mBufferNames[1]);
        gl.glBufferData(GL11.GL_ARRAY_BUFFER,
                mUvBuffer.capacity() * (Float.SIZE / Byte.SIZE),
                mUvBuffer, GL11.GL_STATIC_DRAW);

        gl.glBindBuffer(GL11.GL_ELEMENT_ARRAY_BUFFER, mBufferNames[2]);
        gl.glBufferData(GL11.GL_ELEMENT_ARRAY_BUFFER,
                mIndexBuffer.capacity(),
                mIndexBuffer, GL11.GL_STATIC_DRAW);

        // These buffers are never used again.
        mXyBuffer = null;
        mUvBuffer = null;
        mIndexBuffer = null;
    }

    public void draw(GLCanvas canvas, NinePatchTexture tex, int x, int y) {
        if (mBufferNames == null) {
            prepareBuffers(canvas);
        }
        canvas.drawMesh(tex, x, y, mBufferNames[0], mBufferNames[1],
                mBufferNames[2], mIdxCount);
    }

    public void recycle(GLCanvas canvas) {
        if (mBufferNames != null) {
            canvas.deleteBuffer(mBufferNames[0]);
            canvas.deleteBuffer(mBufferNames[1]);
            canvas.deleteBuffer(mBufferNames[2]);
            mBufferNames = null;
        }
    }
}
