/*
 * 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 java.nio.Buffer;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.CharBuffer;
import java.nio.DoubleBuffer;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.nio.LongBuffer;
import java.nio.ShortBuffer;

import javax.microedition.khronos.opengles.GL10;

public class PointerInfo {

    /**
     * The number of coordinates per vertex. 1..4
     */
    public int mSize;

    /**
     * The type of each coordinate.
     */
    public int mType;

    /**
     * The byte offset between consecutive vertices. 0 means mSize *
     * sizeof(mType)
     */
    public int mStride;
    public Buffer mPointer;
    public ByteBuffer mTempByteBuffer;

    public PointerInfo(int size, int type, int stride, Buffer pointer) {
        mSize = size;
        mType = type;
        mStride = stride;
        mPointer = pointer;
    }

    private int getStride() {
        return mStride > 0 ? mStride : sizeof(mType) * mSize;
    }

    public void bindByteBuffer() {
        mTempByteBuffer = mPointer == null ? null : toByteBuffer(-1, mPointer);
    }

    public void unbindByteBuffer() {
        mTempByteBuffer = null;
    }

    private static int sizeof(int type) {
        switch (type) {
        case GL10.GL_UNSIGNED_BYTE:
            return 1;
        case GL10.GL_BYTE:
            return 1;
        case GL10.GL_SHORT:
            return 2;
        case GL10.GL_FIXED:
            return 4;
        case GL10.GL_FLOAT:
            return 4;
        default:
            return 0;
        }
    }

    private static ByteBuffer toByteBuffer(int byteCount, Buffer input) {
        ByteBuffer result = null;
        boolean convertWholeBuffer = (byteCount < 0);
        if (input instanceof ByteBuffer) {
            ByteBuffer input2 = (ByteBuffer) input;
            int position = input2.position();
            if (convertWholeBuffer) {
                byteCount = input2.limit() - position;
            }
            result = ByteBuffer.allocate(byteCount).order(input2.order());
            for (int i = 0; i < byteCount; i++) {
                result.put(input2.get());
            }
            input2.position(position);
        } else if (input instanceof CharBuffer) {
            CharBuffer input2 = (CharBuffer) input;
            int position = input2.position();
            if (convertWholeBuffer) {
                byteCount = (input2.limit() - position) * 2;
            }
            result = ByteBuffer.allocate(byteCount).order(input2.order());
            CharBuffer result2 = result.asCharBuffer();
            for (int i = 0; i < byteCount / 2; i++) {
                result2.put(input2.get());
            }
            input2.position(position);
        } else if (input instanceof ShortBuffer) {
            ShortBuffer input2 = (ShortBuffer) input;
            int position = input2.position();
            if (convertWholeBuffer) {
                byteCount = (input2.limit() - position)* 2;
            }
            result = ByteBuffer.allocate(byteCount).order(input2.order());
            ShortBuffer result2 = result.asShortBuffer();
            for (int i = 0; i < byteCount / 2; i++) {
                result2.put(input2.get());
            }
            input2.position(position);
        } else if (input instanceof IntBuffer) {
            IntBuffer input2 = (IntBuffer) input;
            int position = input2.position();
            if (convertWholeBuffer) {
                byteCount = (input2.limit() - position) * 4;
            }
            result = ByteBuffer.allocate(byteCount).order(input2.order());
            IntBuffer result2 = result.asIntBuffer();
            for (int i = 0; i < byteCount / 4; i++) {
                result2.put(input2.get());
            }
            input2.position(position);
        } else if (input instanceof FloatBuffer) {
            FloatBuffer input2 = (FloatBuffer) input;
            int position = input2.position();
            if (convertWholeBuffer) {
                byteCount = (input2.limit() - position) * 4;
            }
            result = ByteBuffer.allocate(byteCount).order(input2.order());
            FloatBuffer result2 = result.asFloatBuffer();
            for (int i = 0; i < byteCount / 4; i++) {
                result2.put(input2.get());
            }
            input2.position(position);
        } else if (input instanceof DoubleBuffer) {
            DoubleBuffer input2 = (DoubleBuffer) input;
            int position = input2.position();
            if (convertWholeBuffer) {
                byteCount = (input2.limit() - position) * 8;
            }
            result = ByteBuffer.allocate(byteCount).order(input2.order());
            DoubleBuffer result2 = result.asDoubleBuffer();
            for (int i = 0; i < byteCount / 8; i++) {
                result2.put(input2.get());
            }
            input2.position(position);
        } else if (input instanceof LongBuffer) {
            LongBuffer input2 = (LongBuffer) input;
            int position = input2.position();
            if (convertWholeBuffer) {
                byteCount = (input2.limit() - position) * 8;
            }
            result = ByteBuffer.allocate(byteCount).order(input2.order());
            LongBuffer result2 = result.asLongBuffer();
            for (int i = 0; i < byteCount / 8; i++) {
                result2.put(input2.get());
            }
            input2.position(position);
        } else {
            throw new RuntimeException("Unimplemented Buffer subclass.");
        }
        result.rewind();
        // The OpenGL API will interpret the result in hardware byte order,
        // so we better do that as well:
        result.order(ByteOrder.nativeOrder());
        return result;
    }

    public void getArrayElement(int index, double[] result) {
        if (mTempByteBuffer == null) {
            throw new IllegalArgumentException("undefined pointer");
        }
        if (mStride < 0) {
            throw new IllegalArgumentException("invalid stride");
        }

        int stride = getStride();
        ByteBuffer byteBuffer = mTempByteBuffer;
        int size = mSize;
        int type = mType;
        int sizeofType = sizeof(type);
        int byteOffset = stride * index;

        for (int i = 0; i < size; i++) {
            switch (type) {
            case GL10.GL_BYTE:
            case GL10.GL_UNSIGNED_BYTE:
                result[i] = byteBuffer.get(byteOffset);
                break;
            case GL10.GL_SHORT:
                ShortBuffer shortBuffer = byteBuffer.asShortBuffer();
                result[i] = shortBuffer.get(byteOffset / 2);
                break;
            case GL10.GL_FIXED:
                IntBuffer intBuffer = byteBuffer.asIntBuffer();
                result[i] = intBuffer.get(byteOffset / 4);
                break;
            case GL10.GL_FLOAT:
                FloatBuffer floatBuffer = byteBuffer.asFloatBuffer();
                result[i] = floatBuffer.get(byteOffset / 4);
                break;
            default:
                throw new UnsupportedOperationException("unknown type");
            }
            byteOffset += sizeofType;
        }
    }
}
