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


#ifndef ANDROID_RS_BUILD_FOR_HOST
#include "rsContext.h"
#include <GLES/gl.h>
#else
#include "rsContextHostStub.h"
#include <OpenGL/gl.h>
#endif

using namespace android;
using namespace android::renderscript;


Element::Element(Context *rsc) : ObjectBase(rsc)
{
    mBits = 0;
    mAllocFile = __FILE__;
    mAllocLine = __LINE__;
    mFields = NULL;
    mFieldCount = 0;
    mHasReference = false;
}


Element::~Element()
{
    for (uint32_t ct = 0; ct < mRSC->mStateElement.mElements.size(); ct++) {
        if (mRSC->mStateElement.mElements[ct] == this) {
            mRSC->mStateElement.mElements.removeAt(ct);
            break;
        }
    }
    clear();
}

void Element::clear()
{
    delete [] mFields;
    mFields = NULL;
    mFieldCount = 0;
    mHasReference = false;
}

size_t Element::getSizeBits() const
{
    if (!mFieldCount) {
        return mBits;
    }

    size_t total = 0;
    for (size_t ct=0; ct < mFieldCount; ct++) {
        total += mFields[ct].e->mBits;
    }
    return total;
}

void Element::dumpLOGV(const char *prefix) const
{
    ObjectBase::dumpLOGV(prefix);
    LOGV("%s   Element: components %i,  size %i", prefix, mFieldCount, mBits);
    for (uint32_t ct = 0; ct < mFieldCount; ct++) {
        char buf[1024];
        sprintf(buf, "%s component %i: ", prefix, ct);
        //mComponents[ct]->dumpLOGV(buf);
    }
}

void Element::serialize(OStream *stream) const
{
    // Need to identify ourselves
    stream->addU32((uint32_t)getClassId());

    String8 name(getName());
    stream->addString(&name);

    mComponent.serialize(stream);

    // Now serialize all the fields
    stream->addU32(mFieldCount);
    for(uint32_t ct = 0; ct < mFieldCount; ct++) {
        stream->addString(&mFields[ct].name);
        mFields[ct].e->serialize(stream);
    }
}

Element *Element::createFromStream(Context *rsc, IStream *stream)
{
    // First make sure we are reading the correct object
    RsA3DClassID classID = (RsA3DClassID)stream->loadU32();
    if(classID != RS_A3D_CLASS_ID_ELEMENT) {
        LOGE("element loading skipped due to invalid class id\n");
        return NULL;
    }

    String8 name;
    stream->loadString(&name);

    Element *elem = new Element(rsc);
    elem->mComponent.loadFromStream(stream);
    elem->mBits = elem->mComponent.getBits();
    elem->mHasReference = elem->mComponent.isReference();

    elem->mFieldCount = stream->loadU32();
    if(elem->mFieldCount) {
        uint32_t offset = 0;
        elem->mFields = new ElementField_t [elem->mFieldCount];
        for(uint32_t ct = 0; ct < elem->mFieldCount; ct ++) {
            stream->loadString(&elem->mFields[ct].name);
            Element *fieldElem = Element::createFromStream(rsc, stream);
            elem->mFields[ct].e.set(fieldElem);
            elem->mFields[ct].offsetBits = offset;
            offset += fieldElem->getSizeBits();
            // Check if our sub-elements have references
            if(fieldElem->mHasReference) {
                elem->mHasReference = true;
            }
        }
    }

    // We need to check if this already exists
    for (uint32_t ct=0; ct < rsc->mStateElement.mElements.size(); ct++) {
        Element *ee = rsc->mStateElement.mElements[ct];

        if (!ee->getFieldCount() ) {

            if((ee->getComponent().getType() == elem->getComponent().getType()) &&
               (ee->getComponent().getKind() == elem->getComponent().getKind()) &&
               (ee->getComponent().getIsNormalized() == elem->getComponent().getIsNormalized()) &&
               (ee->getComponent().getVectorSize() == elem->getComponent().getVectorSize())) {
                // Match
                delete elem;
                ee->incUserRef();
                return ee;
            }

        } else if (ee->getFieldCount() == elem->mFieldCount) {

            bool match = true;
            for (uint32_t i=0; i < elem->mFieldCount; i++) {
                if ((ee->mFields[i].e.get() != elem->mFields[i].e.get()) ||
                    (ee->mFields[i].name.length() != elem->mFields[i].name.length()) ||
                    (ee->mFields[i].name != elem->mFields[i].name)) {
                    match = false;
                    break;
                }
            }
            if (match) {
                delete elem;
                ee->incUserRef();
                return ee;
            }

        }
    }

    rsc->mStateElement.mElements.push(elem);
    return elem;
}


const Element * Element::create(Context *rsc, RsDataType dt, RsDataKind dk,
                            bool isNorm, uint32_t vecSize)
{
    // Look for an existing match.
    for (uint32_t ct=0; ct < rsc->mStateElement.mElements.size(); ct++) {
        const Element *ee = rsc->mStateElement.mElements[ct];
        if (!ee->getFieldCount() &&
            (ee->getComponent().getType() == dt) &&
            (ee->getComponent().getKind() == dk) &&
            (ee->getComponent().getIsNormalized() == isNorm) &&
            (ee->getComponent().getVectorSize() == vecSize)) {
            // Match
            ee->incUserRef();
            return ee;
        }
    }

    Element *e = new Element(rsc);
    e->mComponent.set(dt, dk, isNorm, vecSize);
    e->mBits = e->mComponent.getBits();
    e->mHasReference = e->mComponent.isReference();
    rsc->mStateElement.mElements.push(e);
    return e;
}

const Element * Element::create(Context *rsc, size_t count, const Element **ein,
                            const char **nin, const size_t * lengths)
{
    // Look for an existing match.
    for (uint32_t ct=0; ct < rsc->mStateElement.mElements.size(); ct++) {
        const Element *ee = rsc->mStateElement.mElements[ct];
        if (ee->getFieldCount() == count) {
            bool match = true;
            for (uint32_t i=0; i < count; i++) {
                if ((ee->mFields[i].e.get() != ein[i]) ||
                    (ee->mFields[i].name.length() != lengths[i]) ||
                    (ee->mFields[i].name != nin[i])) {
                    match = false;
                    break;
                }
            }
            if (match) {
                ee->incUserRef();
                return ee;
            }
        }
    }

    Element *e = new Element(rsc);
    e->mFields = new ElementField_t [count];
    e->mFieldCount = count;
    size_t bits = 0;
    for (size_t ct=0; ct < count; ct++) {
        e->mFields[ct].e.set(ein[ct]);
        e->mFields[ct].name.setTo(nin[ct], lengths[ct]);
        e->mFields[ct].offsetBits = bits;
        bits += ein[ct]->getSizeBits();

        if (ein[ct]->mHasReference) {
            e->mHasReference = true;
        }
    }

    rsc->mStateElement.mElements.push(e);
    return e;
}

String8 Element::getGLSLType(uint32_t indent) const
{
    String8 s;
    for (uint32_t ct=0; ct < indent; ct++) {
        s.append(" ");
    }

    if (!mFieldCount) {
        // Basic component.
        s.append(mComponent.getGLSLType());
    } else {
        rsAssert(0);
        //s.append("struct ");
        //s.append(getCStructBody(indent));
    }

    return s;
}

void Element::incRefs(const void *ptr) const
{
    if (!mFieldCount) {
        if (mComponent.isReference()) {
            ObjectBase *const*obp = static_cast<ObjectBase *const*>(ptr);
            ObjectBase *ob = obp[0];
            if (ob) ob->incSysRef();
        }
        return;
    }

    const uint8_t *p = static_cast<const uint8_t *>(ptr);
    for (uint32_t i=0; i < mFieldCount; i++) {
        if (mFields[i].e->mHasReference) {
            mFields[i].e->incRefs(&p[mFields[i].offsetBits >> 3]);
        }
    }
}

void Element::decRefs(const void *ptr) const
{
    if (!mFieldCount) {
        if (mComponent.isReference()) {
            ObjectBase *const*obp = static_cast<ObjectBase *const*>(ptr);
            ObjectBase *ob = obp[0];
            if (ob) ob->decSysRef();
        }
        return;
    }

    const uint8_t *p = static_cast<const uint8_t *>(ptr);
    for (uint32_t i=0; i < mFieldCount; i++) {
        if (mFields[i].e->mHasReference) {
            mFields[i].e->decRefs(&p[mFields[i].offsetBits >> 3]);
        }
    }
}


ElementState::ElementState()
{
}

ElementState::~ElementState()
{
    rsAssert(!mElements.size());
}


/////////////////////////////////////////
//

namespace android {
namespace renderscript {

RsElement rsi_ElementCreate(Context *rsc,
                            RsDataType dt,
                            RsDataKind dk,
                            bool norm,
                            uint32_t vecSize)
{
    //LOGE("rsi_ElementCreate %i %i %i %i", dt, dk, norm, vecSize);
    const Element *e = Element::create(rsc, dt, dk, norm, vecSize);
    e->incUserRef();
    return (RsElement)e;
}

RsElement rsi_ElementCreate2(Context *rsc,
                             size_t count,
                             const RsElement * ein,
                             const char ** names,
                             const size_t * nameLengths)
{
    //LOGE("rsi_ElementCreate2 %i", count);
    const Element *e = Element::create(rsc, count, (const Element **)ein, names, nameLengths);
    e->incUserRef();
    return (RsElement)e;
}

void rsi_ElementGetNativeData(Context *rsc, RsElement elem, uint32_t *elemData, uint32_t elemDataSize)
{
    rsAssert(elemDataSize == 5);
    // we will pack mType; mKind; mNormalized; mVectorSize; NumSubElements
    Element *e = static_cast<Element *>(elem);

    (*elemData++) = (uint32_t)e->getType();
    (*elemData++) = (uint32_t)e->getKind();
    (*elemData++) = e->getComponent().getIsNormalized() ? 1 : 0;
    (*elemData++) = e->getComponent().getVectorSize();
    (*elemData++) = e->getFieldCount();

}

void rsi_ElementGetSubElements(Context *rsc, RsElement elem, uint32_t *ids, const char **names, uint32_t dataSize)
{
    Element *e = static_cast<Element *>(elem);
    rsAssert(e->getFieldCount() == dataSize);

    for(uint32_t i = 0; i < dataSize; i ++) {
        ids[i] = (uint32_t)e->getField(i);
        names[i] = e->getFieldName(i);
    }

}


}
}
