/*
 * 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>

#include <utils/Log.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;
        }
    }
    LOGE("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)
{
    //LOGE("tmb  %p %p", vertex, 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();

    //LOGE("Element sizes  %i  %i", tmc->mVertexSizeBits, tmc->mIndexSizeBits);

    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;
    }

    LOGE("Create mesh, triangleCount %i", tm->mTriangleCount);

    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();

    //LOGE("1  %p   ", vtm);
    //LOGE("1.1  %p   %p", tm->mVertexData,  tm->mIndexData);
    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);
    }

    //LOGE("1.2");
    if (first >= tm->mTriangleCount) {
        return;
    }
    if (count >= (tm->mTriangleCount - first)) {
        count = tm->mTriangleCount - first;
    }
    if (!count) {
        return;
    }

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

    //LOGE("2");
    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));

    //LOGE("4");

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

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

}}
