/*
 * Copyright (C) 2009 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.
 */

#include "rsContext.h"

using namespace android;
using namespace android::renderscript;

#include <GLES/gl.h>
#include <GLES/glext.h>

TriangleMesh::TriangleMesh()
{
    mVertexElement = NULL;
    mIndexElement = NULL;
    mVertexData = NULL;
    mIndexData = NULL;
    mTriangleCount = 0;
    mVertexDataSize = 0;
    mIndexDataSize = 0;

    mBufferObjects[0] = 0;
    mBufferObjects[1] = 0;

    mOffsetCoord = 0;
    mOffsetTex = 0;
    mOffsetNorm = 0;

    mSizeCoord = 0;
    mSizeTex = 0;
    mSizeNorm = 0;

}

TriangleMesh::~TriangleMesh()
{
    free(mVertexData);
    free(mIndexData);
}



TriangleMeshContext::TriangleMeshContext()
{
    clear();
}

TriangleMeshContext::~TriangleMeshContext()
{
}

void TriangleMeshContext::clear()
{
    mVertexElement = NULL;
    mVertexSizeBits = 0;
    mIndexElement = NULL;
    mIndexSizeBits = 0;
    mTriangleCount = 0;
    mVertexData.clear();
    mIndexData.clear();
}

void TriangleMesh::analyzeElement()
{
    for (uint32_t ct=0; ct < mVertexElement->getComponentCount(); ct++) {
        const Component *c = mVertexElement->getComponent(ct);

        if (c->getKind() == Component::X) {
            rsAssert(mSizeCoord == 0);
            mSizeCoord = 1;
            mOffsetCoord = ct;
        }
        if (c->getKind() == Component::Y) {
            rsAssert(mSizeCoord == 1);
            mSizeCoord = 2;
        }
        if (c->getKind() == Component::Z) {
            rsAssert(mSizeCoord == 2);
            mSizeCoord = 3;
        }
        if (c->getKind() == Component::W) {
            rsAssert(mSizeCoord == 4);
            mSizeCoord = 4;
        }

        if (c->getKind() == Component::NX) {
            rsAssert(mSizeNorm == 0);
            mSizeNorm = 1;
            mOffsetNorm = ct;
        }
        if (c->getKind() == Component::NY) {
            rsAssert(mSizeNorm == 1);
            mSizeNorm = 2;
        }
        if (c->getKind() == Component::NZ) {
            rsAssert(mSizeNorm == 2);
            mSizeNorm = 3;
        }

        if (c->getKind() == Component::S) {
            rsAssert(mSizeTex == 0);
            mSizeTex = 1;
            mOffsetTex = ct;
        }
        if (c->getKind() == Component::T) {
            rsAssert(mSizeTex == 1);
            mSizeTex = 2;
        }
    }
    LOGV("TriangleMesh %i,%i  %i,%i  %i,%i", mSizeCoord, mOffsetCoord, mSizeNorm, mOffsetNorm, mSizeTex, mOffsetTex);

}


namespace android {
namespace renderscript {

void rsi_TriangleMeshBegin(Context *rsc, RsElement vertex, RsElement index)
{
    TriangleMeshContext *tmc = &rsc->mStateTriangleMesh;

    tmc->clear();
    tmc->mVertexElement = static_cast<Element *>(vertex);
    tmc->mVertexSizeBits = tmc->mVertexElement->getSizeBits();
    tmc->mIndexElement = static_cast<Element *>(index);
    tmc->mIndexSizeBits = tmc->mIndexElement->getSizeBits();

    assert(!(tmc->mVertexSizeBits & 0x7));
    assert(!(tmc->mIndexSizeBits & 0x7));
}

void rsi_TriangleMeshAddVertex(Context *rsc, const void *data)
{
    TriangleMeshContext *tmc = &rsc->mStateTriangleMesh;

    // todo: Make this efficient.
    for (uint32_t ct = 0; (ct * 8) < tmc->mVertexSizeBits; ct++) {
        tmc->mVertexData.add(static_cast<const uint8_t *>(data) [ct]);
    }
}

void rsi_TriangleMeshAddTriangle(Context *rsc, uint32_t idx1, uint32_t idx2, uint32_t idx3)
{
    TriangleMeshContext *tmc = &rsc->mStateTriangleMesh;

    // todo: Make this efficient.
    switch(tmc->mIndexSizeBits) {
    case 16:
        tmc->mIndexData.add(idx1);
        tmc->mIndexData.add(idx2);
        tmc->mIndexData.add(idx3);
        break;
    default:
        assert(0);
    }

    tmc->mTriangleCount++;
}

RsTriangleMesh rsi_TriangleMeshCreate(Context *rsc)
{
    TriangleMeshContext *tmc = &rsc->mStateTriangleMesh;

    TriangleMesh * tm = new TriangleMesh();
    if (!tm) {
        LOGE("rsTriangleMeshCreate: Error OUT OF MEMORY");
        // error
        return 0;
    }

    tm->mTriangleCount = tmc->mTriangleCount;
    tm->mIndexDataSize = tmc->mIndexData.size() * tmc->mIndexSizeBits >> 3;
    tm->mVertexDataSize = tmc->mVertexData.size();
    tm->mIndexElement = tmc->mIndexElement;
    tm->mVertexElement = tmc->mVertexElement;

    tm->mIndexData = malloc(tm->mIndexDataSize);
    tm->mVertexData = malloc(tm->mVertexDataSize);
    if (!tm->mIndexData || !tm->mVertexData) {
        LOGE("rsTriangleMeshCreate: Error OUT OF MEMORY");
        delete tm;
        return 0;
    }

    memcpy(tm->mVertexData, tmc->mVertexData.array(), tm->mVertexDataSize);
    memcpy(tm->mIndexData, tmc->mIndexData.array(), tm->mIndexDataSize);
    tm->analyzeElement();

    return tm;
}

void rsi_TriangleMeshDestroy(Context *rsc, RsTriangleMesh vtm)
{
    TriangleMeshContext *tmc = &rsc->mStateTriangleMesh;
    TriangleMesh * tm = static_cast<TriangleMesh *>(vtm);

    free(tm->mIndexData);
    free(tm->mVertexData);
    delete tm;
}



void rsi_TriangleMeshRenderRange(Context *rsc, RsTriangleMesh vtm, uint32_t first, uint32_t count)
{
    TriangleMesh * tm = static_cast<TriangleMesh *>(vtm);

    rsc->setupCheck();

    if (!tm->mBufferObjects[0]) {
        glGenBuffers(2, &tm->mBufferObjects[0]);

        glBindBuffer(GL_ARRAY_BUFFER, tm->mBufferObjects[0]);
        glBufferData(GL_ARRAY_BUFFER, tm->mVertexDataSize, tm->mVertexData, GL_STATIC_DRAW);
        glBindBuffer(GL_ARRAY_BUFFER, 0);

        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, tm->mBufferObjects[1]);
        glBufferData(GL_ELEMENT_ARRAY_BUFFER, tm->mIndexDataSize, tm->mIndexData, GL_STATIC_DRAW);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
    }

    if (first >= tm->mTriangleCount) {
        return;
    }
    if (count >= (tm->mTriangleCount - first)) {
        count = tm->mTriangleCount - first;
    }
    if (!count) {
        return;
    }

    const float *f = (const float *)tm->mVertexData;

    glBindBuffer(GL_ARRAY_BUFFER, tm->mBufferObjects[0]);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, tm->mBufferObjects[1]);

    glEnableClientState(GL_VERTEX_ARRAY);
    glVertexPointer(tm->mSizeCoord, 
                    GL_FLOAT, 
                    tm->mVertexElement->getSizeBytes(), 
                    (void *)tm->mVertexElement->getComponentOffsetBytes(tm->mOffsetCoord));

    if (tm->mSizeTex) {
        glEnableClientState(GL_TEXTURE_COORD_ARRAY);
        glTexCoordPointer(tm->mSizeTex, 
                          GL_FLOAT, 
                          tm->mVertexElement->getSizeBytes(), 
                          (void *)tm->mVertexElement->getComponentOffsetBytes(tm->mOffsetTex));
    } else {
        glDisableClientState(GL_TEXTURE_COORD_ARRAY);
    }

    if (tm->mSizeNorm) {
        glEnableClientState(GL_NORMAL_ARRAY);
        glNormalPointer(GL_FLOAT, 
                        tm->mVertexElement->getSizeBytes(), 
                        (void *)tm->mVertexElement->getComponentOffsetBytes(tm->mOffsetNorm));
    } else {
        glDisableClientState(GL_NORMAL_ARRAY);
    }

    glDrawElements(GL_TRIANGLES, count * 3, GL_UNSIGNED_SHORT, (GLvoid *)(first * 3 * 2));

    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
}

void rsi_TriangleMeshRender(Context *rsc, RsTriangleMesh vtm)
{
    rsi_TriangleMeshRenderRange(rsc, vtm, 0, 0xffffff);
}

}}
