/*
 ** Copyright 2011, 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.glesv2debugger;

import com.android.glesv2debugger.DebuggerMessage.Message;

import java.nio.ByteBuffer;
import java.util.HashMap;

class GLBuffer {
    GLEnum usage;
    GLEnum target;
    ByteBuffer data;
}

class GLAttribPointer {
    int size; // number of values per vertex
    GLEnum type; // data type
    int stride; // bytes
    int ptr; // pointer in debugger server or byte offset into buffer
    GLBuffer buffer;
    boolean normalized;
    boolean enabled;
}

public class GLServerVertex {

    HashMap<Integer, GLBuffer> buffers;
    GLBuffer attribBuffer, indexBuffer; // current binding
    GLAttribPointer attribPointers[];
    float defaultAttribs[][];
    int maxAttrib;

    public GLServerVertex() {
        buffers = new HashMap<Integer, GLBuffer>();
        buffers.put(0, null);
        attribPointers = new GLAttribPointer[16];
        for (int i = 0; i < attribPointers.length; i++)
            attribPointers[i] = new GLAttribPointer();
        defaultAttribs = new float[16][4];
        for (int i = 0; i < defaultAttribs.length; i++) {
            defaultAttribs[i][0] = 0;
            defaultAttribs[i][1] = 0;
            defaultAttribs[i][2] = 0;
            defaultAttribs[i][3] = 1;
        }
    }

    // void API_ENTRY(glBindBuffer)(GLenum target, GLuint buffer)
    public void glBindBuffer(Message msg) {
        if (GLEnum.valueOf(msg.getArg0()) == GLEnum.GL_ARRAY_BUFFER) {
            attribBuffer = buffers.get(msg.getArg1());
            if (null != attribBuffer)
                attribBuffer.target = GLEnum.GL_ARRAY_BUFFER;
        } else if (GLEnum.valueOf(msg.getArg0()) == GLEnum.GL_ELEMENT_ARRAY_BUFFER) {
            indexBuffer = buffers.get(msg.getArg1());
            if (null != indexBuffer)
                indexBuffer.target = GLEnum.GL_ELEMENT_ARRAY_BUFFER;
        } else
            assert false;
    }

    // void API_ENTRY(glBufferData)(GLenum target, GLsizeiptr size, const
    // GLvoid:size:in data, GLenum usage)
    public void glBufferData(Message msg) {
        if (GLEnum.valueOf(msg.getArg0()) == GLEnum.GL_ARRAY_BUFFER) {
            attribBuffer.usage = GLEnum.valueOf(msg.getArg3());
            attribBuffer.data = msg.getData().asReadOnlyByteBuffer();
        } else if (GLEnum.valueOf(msg.getArg0()) == GLEnum.GL_ELEMENT_ARRAY_BUFFER) {
            indexBuffer.usage = GLEnum.valueOf(msg.getArg3());
            indexBuffer.data = msg.getData().asReadOnlyByteBuffer();
        } else
            assert false;
    }

    // void API_ENTRY(glBufferSubData)(GLenum target, GLintptr offset,
    // GLsizeiptr size, const GLvoid:size:in data)
    public void glBufferSubData(Message msg) {
        if (GLEnum.valueOf(msg.getArg0()) == GLEnum.GL_ARRAY_BUFFER) {
            if (attribBuffer.data.isReadOnly()) {
                ByteBuffer buffer = ByteBuffer.allocate(attribBuffer.data.capacity());
                buffer.put(attribBuffer.data);
                attribBuffer.data = buffer;
            }
            attribBuffer.data.position(msg.getArg1());
            attribBuffer.data.put(msg.getData().asReadOnlyByteBuffer());
        } else if (GLEnum.valueOf(msg.getArg0()) == GLEnum.GL_ELEMENT_ARRAY_BUFFER) {
            if (indexBuffer.data.isReadOnly()) {
                ByteBuffer buffer = ByteBuffer.allocate(indexBuffer.data.capacity());
                buffer.put(indexBuffer.data);
                indexBuffer.data = buffer;
            }
            indexBuffer.data.position(msg.getArg1());
            indexBuffer.data.put(msg.getData().asReadOnlyByteBuffer());
        } else
            assert false;
    }

    // void glDeleteBuffers(GLsizei n, const GLuint* buffers)
    public void glDeleteBuffers(Message msg) {
        final int n = msg.getArg0();
        final ByteBuffer names = msg.getData().asReadOnlyByteBuffer();
        for (int i = 0; i < n; i++) {
            int name = Integer.reverseBytes(names.getInt());
            GLBuffer buffer = buffers.get(name);
            for (int j = 0; j < attribPointers.length; j++)
                if (attribPointers[j].buffer == buffer) {
                    attribPointers[j].buffer = null;
                    attribPointers[j].enabled = false;
                }
            if (attribBuffer == buffer)
                attribBuffer = null;
            if (indexBuffer == buffer)
                indexBuffer = null;
            buffers.remove(name);
        }
    }

    // void glDisableVertexAttribArray(GLuint index)
    public void glDisableVertexAttribArray(Message msg) {
        attribPointers[msg.getArg0()].enabled = false;
    }

    float FetchConvert(final ByteBuffer src, final GLEnum type, final boolean normalized) {
        if (GLEnum.GL_FLOAT == type)
            return Float.intBitsToFloat(Integer.reverseBytes(src.getInt()));
        else if (GLEnum.GL_UNSIGNED_INT == type)
            if (normalized)
                return (Integer.reverseBytes(src.getInt()) & 0xffffffffL) / (2e32f - 1);
            else 
                return Integer.reverseBytes(src.getInt()) & 0xffffffffL;
        else if (GLEnum.GL_INT == type)
            if (normalized)
                return (Integer.reverseBytes(src.getInt()) * 2 + 1) / (2e32f - 1);
            else 
                return Integer.reverseBytes(src.getInt());
        else if (GLEnum.GL_UNSIGNED_SHORT == type)
            if (normalized)
                return (Short.reverseBytes(src.getShort()) & 0xffff) / (2e16f - 1);
            else 
                return Short.reverseBytes(src.getShort()) & 0xffff;
        else if (GLEnum.GL_SHORT == type)
            if (normalized)
                return (Short.reverseBytes(src.getShort()) * 2 + 1) / (2e16f - 1);
            else 
                return Short.reverseBytes(src.getShort());
        else if (GLEnum.GL_UNSIGNED_BYTE == type)
            if (normalized)
                return (src.get() & 0xff) / (2e8f - 1);
            else 
                return src.get() & 0xff;
        else if (GLEnum.GL_BYTE == type)
            if (normalized)
                return (src.get() * 2 + 1) / (2e8f - 1);
            else 
                return src.get();
        else if (GLEnum.GL_FIXED == type)
            if (normalized)
                return (Integer.reverseBytes(src.getInt()) * 2 + 1) / (2e32f - 1);
            else
                return Integer.reverseBytes(src.getInt()) / (2e16f);
        else
            assert false;
        return 0;
    }

    void Fetch(int index, final ByteBuffer nonVBO, final ByteBuffer dst) {
        for (int i = 0; i < maxAttrib; i++) {
            final GLAttribPointer attrib = attribPointers[i];
            int size = 0;
            if (attrib.enabled)
                size = attrib.size;
            if (null != attrib.buffer) {
                final ByteBuffer src = attrib.buffer.data;
                src.position(attrib.ptr + i * attrib.stride);
                dst.putFloat(FetchConvert(src, attrib.type, attrib.normalized));
            } else
                for (int j = 0; j < size; j++)
                    dst.putFloat(FetchConvert(nonVBO, attrib.type, attrib.normalized));
            if (size < 1)
                dst.putFloat(defaultAttribs[i][0]);
            if (size < 2)
                dst.putFloat(defaultAttribs[i][1]);
            if (size < 3)
                dst.putFloat(defaultAttribs[i][2]);
            if (size < 4)
                dst.putFloat(defaultAttribs[i][3]);
        }
    }

    // void glDrawArrays(GLenum mode, GLint first, GLsizei count)
    public Message glDrawArrays(Message msg) {
        maxAttrib = msg.getArg7();
        final int first = msg.getArg1(), count = msg.getArg2();
        final ByteBuffer buffer = ByteBuffer.allocate(4 * 4 * maxAttrib * count);
        ByteBuffer arrays = null;
        if (msg.hasData()) // server sends user pointer attribs
            arrays = msg.getData().asReadOnlyByteBuffer();
        for (int i = first; i < first + count; i++)
            Fetch(i, arrays, buffer);
        assert null == arrays || arrays.remaining() == 0;
        buffer.rewind();
        return msg.toBuilder().setData(com.google.protobuf.ByteString.copyFrom(buffer))
                .setArg8(GLEnum.GL_FLOAT.value).build();
    }

    // void glDrawElements(GLenum mode, GLsizei count, GLenum type, const
    // GLvoid* indices)
    public Message glDrawElements(Message msg) {
        maxAttrib = msg.getArg7();
        final int count = msg.getArg1();
        final GLEnum type = GLEnum.valueOf(msg.getArg2());
        final ByteBuffer buffer = ByteBuffer.allocate(4 * 4 * maxAttrib * count);
        ByteBuffer arrays = null, index = null;
        if (msg.hasData()) // server sends user pointer attribs
            arrays = msg.getData().asReadOnlyByteBuffer();
        if (null == indexBuffer)
            index = arrays; // server also interleaves user pointer indices
        else {
            index = indexBuffer.data;
            index.position(msg.getArg3());
        }
        if (GLEnum.GL_UNSIGNED_SHORT == type)
            for (int i = 0; i < count; i++)
                Fetch(Short.reverseBytes(index.getShort()) & 0xffff, arrays, buffer);
        else if (GLEnum.GL_UNSIGNED_BYTE == type)
            for (int i = 0; i < count; i++)
                Fetch(index.get() & 0xff, arrays, buffer);
        else
            assert false;
        assert null == arrays || arrays.remaining() == 0;
        buffer.rewind();
        return msg.toBuilder().setData(com.google.protobuf.ByteString.copyFrom(buffer))
                .setArg8(GLEnum.GL_FLOAT.value).build();
    }

    // void glEnableVertexAttribArray(GLuint index)
    public void glEnableVertexAttribArray(Message msg) {
        attribPointers[msg.getArg0()].enabled = true;
    }

    // void API_ENTRY(glGenBuffers)(GLsizei n, GLuint:n:out buffers)
    public void glGenBuffers(Message msg) {
        final int n = msg.getArg0();
        final ByteBuffer buffer = msg.getData().asReadOnlyByteBuffer();
        for (int i = 0; i < n; i++) {
            int name = Integer.reverseBytes(buffer.getInt());
            if (!buffers.containsKey(name))
                buffers.put(name, new GLBuffer());
        }
    }

    // void glVertexAttribPointer(GLuint index, GLint size, GLenum type,
    // GLboolean normalized, GLsizei stride, const GLvoid* ptr)
    public void glVertexAttribPointer(Message msg) {
        GLAttribPointer attrib = attribPointers[msg.getArg0()];
        attrib.size = msg.getArg1();
        attrib.type = GLEnum.valueOf(msg.getArg2());
        attrib.normalized = msg.getArg3() != 0;
        attrib.stride = msg.getArg4();
        if (0 == attrib.stride)
            attrib.stride = attrib.size * 4;
        attrib.ptr = msg.getArg5();
        attrib.buffer = attribBuffer;
    }

    // void glVertexAttrib1f(GLuint indx, GLfloat x)
    public void glVertexAttrib1f(Message msg) {
        glVertexAttrib4f(msg.getArg0(), Float.intBitsToFloat(Integer.reverseBytes(msg.getArg1())),
                0, 0, 1);
    }

    // void glVertexAttrib1fv(GLuint indx, const GLfloat* values)
    public void glVertexAttrib1fv(Message msg) {
        final ByteBuffer values = msg.getData().asReadOnlyByteBuffer();
        glVertexAttrib4f(msg.getArg0(),
                Float.intBitsToFloat(Integer.reverseBytes(values.getInt())),
                0, 0, 1);
    }

    // void glVertexAttrib2f(GLuint indx, GLfloat x, GLfloat y)
    public void glVertexAttrib2f(Message msg) {
        glVertexAttrib4f(msg.getArg0(), Float.intBitsToFloat(Integer.reverseBytes(msg.getArg1())),
                Float.intBitsToFloat(Integer.reverseBytes(msg.getArg2())), 0, 1);
    }

    // void glVertexAttrib2fv(GLuint indx, const GLfloat* values)
    public void glVertexAttrib2fv(Message msg) {
        final ByteBuffer values = msg.getData().asReadOnlyByteBuffer();
        glVertexAttrib4f(msg.getArg0(),
                Float.intBitsToFloat(Integer.reverseBytes(values.getInt())),
                Float.intBitsToFloat(Integer.reverseBytes(values.getInt())), 0, 1);
    }

    // void glVertexAttrib3f(GLuint indx, GLfloat x, GLfloat y, GLfloat z)
    public void glVertexAttrib3f(Message msg) {
        glVertexAttrib4f(msg.getArg0(), Float.intBitsToFloat(Integer.reverseBytes(msg.getArg1())),
                Float.intBitsToFloat(Integer.reverseBytes(msg.getArg2())),
                Float.intBitsToFloat(Integer.reverseBytes(msg.getArg3())), 1);
    }

    // void glVertexAttrib3fv(GLuint indx, const GLfloat* values)
    public void glVertexAttrib3fv(Message msg) {
        final ByteBuffer values = msg.getData().asReadOnlyByteBuffer();
        glVertexAttrib4f(msg.getArg0(),
                Float.intBitsToFloat(Integer.reverseBytes(values.getInt())),
                Float.intBitsToFloat(Integer.reverseBytes(values.getInt())),
                Float.intBitsToFloat(Integer.reverseBytes(values.getInt())), 1);
    }

    public void glVertexAttrib4f(Message msg) {
        glVertexAttrib4f(msg.getArg0(), Float.intBitsToFloat(Integer.reverseBytes(msg.getArg1())),
                Float.intBitsToFloat(Integer.reverseBytes(msg.getArg2())),
                Float.intBitsToFloat(Integer.reverseBytes(msg.getArg3())),
                Float.intBitsToFloat(Integer.reverseBytes(msg.getArg4())));
    }

    void glVertexAttrib4f(int indx, float x, float y, float z, float w) {
        defaultAttribs[indx][0] = x;
        defaultAttribs[indx][1] = y;
        defaultAttribs[indx][2] = z;
        defaultAttribs[indx][3] = w;
    }

    // void glVertexAttrib4fv(GLuint indx, const GLfloat* values)
    public void glVertexAttrib4fv(Message msg) {
        final ByteBuffer values = msg.getData().asReadOnlyByteBuffer();
        glVertexAttrib4f(msg.getArg0(),
                Float.intBitsToFloat(Integer.reverseBytes(values.getInt())),
                Float.intBitsToFloat(Integer.reverseBytes(values.getInt())),
                Float.intBitsToFloat(Integer.reverseBytes(values.getInt())),
                Float.intBitsToFloat(Integer.reverseBytes(values.getInt())));
    }
}
