/*
Open Asset Import Library (assimp)
----------------------------------------------------------------------

Copyright (c) 2006-2017, assimp team

All rights reserved.

Redistribution and use of this software in source and binary forms,
with or without modification, are permitted provided that the
following conditions are met:

* Redistributions of source code must retain the above
  copyright notice, this list of conditions and the
  following disclaimer.

* Redistributions in binary form must reproduce the above
  copyright notice, this list of conditions and the
  following disclaimer in the documentation and/or other
  materials provided with the distribution.

* Neither the name of the assimp team, nor the names of its
  contributors may be used to endorse or promote products
  derived from this software without specific prior
  written permission of the assimp team.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

----------------------------------------------------------------------
*/

/** @file  MaterialSystem.cpp
 *  @brief Implementation of the material system of the library
 */

#include "Hash.h"
#include "fast_atof.h"
#include "ParsingUtils.h"
#include "MaterialSystem.h"
#include <assimp/types.h>
#include <assimp/material.h>
#include <assimp/DefaultLogger.hpp>
#include "Macros.h"

using namespace Assimp;

// ------------------------------------------------------------------------------------------------
// Get a specific property from a material
aiReturn aiGetMaterialProperty(const aiMaterial* pMat,
    const char* pKey,
    unsigned int type,
    unsigned int index,
    const aiMaterialProperty** pPropOut)
{
    ai_assert (pMat != NULL);
    ai_assert (pKey != NULL);
    ai_assert (pPropOut != NULL);

    /*  Just search for a property with exactly this name ..
     *  could be improved by hashing, but it's possibly
     *  no worth the effort (we're bound to C structures,
     *  thus std::map or derivates are not applicable. */
    for ( unsigned int i = 0; i < pMat->mNumProperties; ++i ) {
        aiMaterialProperty* prop = pMat->mProperties[i];

        if (prop /* just for safety ... */
            && 0 == strcmp( prop->mKey.data, pKey )
            && (UINT_MAX == type  || prop->mSemantic == type) /* UINT_MAX is a wildcard, but this is undocumented :-) */
            && (UINT_MAX == index || prop->mIndex == index))
        {
            *pPropOut = pMat->mProperties[i];
            return AI_SUCCESS;
        }
    }
    *pPropOut = NULL;
    return AI_FAILURE;
}

// ------------------------------------------------------------------------------------------------
// Get an array of floating-point values from the material.
aiReturn aiGetMaterialFloatArray(const aiMaterial* pMat,
    const char* pKey,
    unsigned int type,
    unsigned int index,
    ai_real* pOut,
    unsigned int* pMax)
{
    ai_assert (pOut != NULL);
    ai_assert (pMat != NULL);

    const aiMaterialProperty* prop;
    aiGetMaterialProperty(pMat,pKey,type,index, (const aiMaterialProperty**) &prop);
    if (!prop) {
        return AI_FAILURE;
    }

    // data is given in floats, convert to ai_real
    unsigned int iWrite = 0;
    if( aiPTI_Float == prop->mType || aiPTI_Buffer == prop->mType)  {
        iWrite = prop->mDataLength / sizeof(float);
        if (pMax) {
            iWrite = std::min(*pMax,iWrite); ;
        }
        for (unsigned int a = 0; a < iWrite;++a)    {
            pOut[a] = static_cast<ai_real> ( reinterpret_cast<float*>(prop->mData)[a] );
        }
        if (pMax) {
            *pMax = iWrite;
        }
    }
    // data is given in doubles, convert to float
    else if( aiPTI_Double == prop->mType)  {
        iWrite = prop->mDataLength / sizeof(double);
        if (pMax) {
            iWrite = std::min(*pMax,iWrite); ;
        }
        for (unsigned int a = 0; a < iWrite;++a)    {
            pOut[a] = static_cast<ai_real> ( reinterpret_cast<double*>(prop->mData)[a] );
        }
        if (pMax) {
            *pMax = iWrite;
        }
    }
    // data is given in ints, convert to float
    else if( aiPTI_Integer == prop->mType)  {
        iWrite = prop->mDataLength / sizeof(int32_t);
        if (pMax) {
            iWrite = std::min(*pMax,iWrite); ;
        }
        for (unsigned int a = 0; a < iWrite;++a)    {
            pOut[a] = static_cast<ai_real> ( reinterpret_cast<int32_t*>(prop->mData)[a] );
        }
        if (pMax) {
            *pMax = iWrite;
        }
    }
    // a string ... read floats separated by spaces
    else {
        if (pMax) {
            iWrite = *pMax;
        }
        // strings are zero-terminated with a 32 bit length prefix, so this is safe
        const char *cur = prop->mData + 4;
        ai_assert( prop->mDataLength >= 5 );
        ai_assert( !prop->mData[ prop->mDataLength - 1 ] );
        for ( unsigned int a = 0; ;++a) {
            cur = fast_atoreal_move<ai_real>(cur,pOut[a]);
            if ( a==iWrite-1 ) {
                break;
            }
            if ( !IsSpace(*cur) ) {
                DefaultLogger::get()->error("Material property" + std::string(pKey) +
                    " is a string; failed to parse a float array out of it.");
                return AI_FAILURE;
            }
        }

        if (pMax) {
            *pMax = iWrite;
        }
    }
    return AI_SUCCESS;
}

// ------------------------------------------------------------------------------------------------
// Get an array if integers from the material
aiReturn aiGetMaterialIntegerArray(const aiMaterial* pMat,
    const char* pKey,
    unsigned int type,
    unsigned int index,
    int* pOut,
    unsigned int* pMax)
{
    ai_assert (pOut != NULL);
    ai_assert (pMat != NULL);

    const aiMaterialProperty* prop;
    aiGetMaterialProperty(pMat,pKey,type,index,(const aiMaterialProperty**) &prop);
    if (!prop) {
        return AI_FAILURE;
    }

    // data is given in ints, simply copy it
    unsigned int iWrite = 0;
    if( aiPTI_Integer == prop->mType || aiPTI_Buffer == prop->mType)    {
        iWrite = prop->mDataLength / sizeof(int32_t);
        if (pMax) {
            iWrite = std::min(*pMax,iWrite); ;
        }
        for (unsigned int a = 0; a < iWrite;++a) {
            pOut[a] = static_cast<int>(reinterpret_cast<int32_t*>(prop->mData)[a]);
        }
        if (pMax) {
            *pMax = iWrite;
        }
    }
    // data is given in floats convert to int
    else if( aiPTI_Float == prop->mType)    {
        iWrite = prop->mDataLength / sizeof(float);
        if (pMax) {
            iWrite = std::min(*pMax,iWrite); ;
        }
        for (unsigned int a = 0; a < iWrite;++a) {
            pOut[a] = static_cast<int>(reinterpret_cast<float*>(prop->mData)[a]);
        }
        if (pMax) {
            *pMax = iWrite;
        }
    }
    // it is a string ... no way to read something out of this
    else    {
        if (pMax) {
            iWrite = *pMax;
        }
        // strings are zero-terminated with a 32 bit length prefix, so this is safe
        const char *cur =  prop->mData+4;
        ai_assert( prop->mDataLength >= 5 );
        ai_assert( !prop->mData[ prop->mDataLength - 1 ] );
        for (unsigned int a = 0; ;++a) {
            pOut[a] = strtol10(cur,&cur);
            if(a==iWrite-1) {
                break;
            }
            if(!IsSpace(*cur)) {
                DefaultLogger::get()->error("Material property" + std::string(pKey) +
                    " is a string; failed to parse an integer array out of it.");
                return AI_FAILURE;
            }
        }

        if (pMax) {
            *pMax = iWrite;
        }
    }
    return AI_SUCCESS;
}

// ------------------------------------------------------------------------------------------------
// Get a color (3 or 4 floats) from the material
aiReturn aiGetMaterialColor(const aiMaterial* pMat,
    const char* pKey,
    unsigned int type,
    unsigned int index,
    aiColor4D* pOut)
{
    unsigned int iMax = 4;
    const aiReturn eRet = aiGetMaterialFloatArray(pMat,pKey,type,index,(ai_real*)pOut,&iMax);

    // if no alpha channel is defined: set it to 1.0
    if (3 == iMax) {
        pOut->a = 1.0;
    }

    return eRet;
}

// ------------------------------------------------------------------------------------------------
// Get a aiUVTransform (4 floats) from the material
aiReturn aiGetMaterialUVTransform(const aiMaterial* pMat,
    const char* pKey,
    unsigned int type,
    unsigned int index,
    aiUVTransform* pOut)
{
    unsigned int iMax = 4;
    return  aiGetMaterialFloatArray(pMat,pKey,type,index,(ai_real*)pOut,&iMax);
}

// ------------------------------------------------------------------------------------------------
// Get a string from the material
aiReturn aiGetMaterialString(const aiMaterial* pMat,
    const char* pKey,
    unsigned int type,
    unsigned int index,
    aiString* pOut)
{
    ai_assert (pOut != NULL);

    const aiMaterialProperty* prop;
    aiGetMaterialProperty(pMat,pKey,type,index,(const aiMaterialProperty**)&prop);
    if (!prop) {
        return AI_FAILURE;
    }

    if( aiPTI_String == prop->mType) {
        ai_assert(prop->mDataLength>=5);

        // The string is stored as 32 but length prefix followed by zero-terminated UTF8 data
        pOut->length = static_cast<unsigned int>(*reinterpret_cast<uint32_t*>(prop->mData));

        ai_assert( pOut->length+1+4==prop->mDataLength );
        ai_assert( !prop->mData[ prop->mDataLength - 1 ] );
        memcpy(pOut->data,prop->mData+4,pOut->length+1);
    }
    else {
        // TODO - implement lexical cast as well
        DefaultLogger::get()->error("Material property" + std::string(pKey) +
            " was found, but is no string" );
        return AI_FAILURE;
    }
    return AI_SUCCESS;
}

// ------------------------------------------------------------------------------------------------
// Get the number of textures on a particular texture stack
ASSIMP_API unsigned int aiGetMaterialTextureCount(const C_STRUCT aiMaterial* pMat,
    C_ENUM aiTextureType type)
{
    ai_assert (pMat != NULL);

    // Textures are always stored with ascending indices (ValidateDS provides a check, so we don't need to do it again)
    unsigned int max = 0;
    for (unsigned int i = 0; i < pMat->mNumProperties;++i) {
        aiMaterialProperty* prop = pMat->mProperties[i];

        if ( prop /* just a sanity check ... */
            && 0 == strcmp( prop->mKey.data, _AI_MATKEY_TEXTURE_BASE )
            && prop->mSemantic == type) {

            max = std::max(max,prop->mIndex+1);
        }
    }
    return max;
}

// ------------------------------------------------------------------------------------------------
aiReturn aiGetMaterialTexture(const C_STRUCT aiMaterial* mat,
    aiTextureType type,
    unsigned int  index,
    C_STRUCT aiString* path,
    aiTextureMapping* _mapping  /*= NULL*/,
    unsigned int* uvindex       /*= NULL*/,
    ai_real* blend              /*= NULL*/,
    aiTextureOp* op             /*= NULL*/,
    aiTextureMapMode* mapmode   /*= NULL*/,
    unsigned int* flags         /*= NULL*/
    )
{
    ai_assert(NULL != mat && NULL != path);

    // Get the path to the texture
    if (AI_SUCCESS != aiGetMaterialString(mat,AI_MATKEY_TEXTURE(type,index),path))  {
        return AI_FAILURE;
    }
    // Determine mapping type
    aiTextureMapping mapping = aiTextureMapping_UV;
    aiGetMaterialInteger(mat,AI_MATKEY_MAPPING(type,index),(int*)&mapping);
    if (_mapping)
        *_mapping = mapping;

    // Get UV index
    if (aiTextureMapping_UV == mapping && uvindex)  {
        aiGetMaterialInteger(mat,AI_MATKEY_UVWSRC(type,index),(int*)uvindex);
    }
    // Get blend factor
    if (blend)  {
        aiGetMaterialFloat(mat,AI_MATKEY_TEXBLEND(type,index),blend);
    }
    // Get texture operation
    if (op){
        aiGetMaterialInteger(mat,AI_MATKEY_TEXOP(type,index),(int*)op);
    }
    // Get texture mapping modes
    if (mapmode)    {
        aiGetMaterialInteger(mat,AI_MATKEY_MAPPINGMODE_U(type,index),(int*)&mapmode[0]);
        aiGetMaterialInteger(mat,AI_MATKEY_MAPPINGMODE_V(type,index),(int*)&mapmode[1]);
    }
    // Get texture flags
    if (flags){
        aiGetMaterialInteger(mat,AI_MATKEY_TEXFLAGS(type,index),(int*)flags);
    }
    return AI_SUCCESS;
}

static const unsigned int DefaultNumAllocated = 5;

// ------------------------------------------------------------------------------------------------
// Construction. Actually the one and only way to get an aiMaterial instance
aiMaterial::aiMaterial() 
: mProperties( NULL )
, mNumProperties( 0 )
, mNumAllocated( DefaultNumAllocated ) {
    // Allocate 5 entries by default
    mProperties = new aiMaterialProperty*[ DefaultNumAllocated ];
}

// ------------------------------------------------------------------------------------------------
aiMaterial::~aiMaterial()
{
    Clear();

    delete[] mProperties;
}

// ------------------------------------------------------------------------------------------------
void aiMaterial::Clear()
{
    for (unsigned int i = 0; i < mNumProperties;++i)    {
        // delete this entry
        delete mProperties[i];
        AI_DEBUG_INVALIDATE_PTR(mProperties[i]);
    }
    mNumProperties = 0;

    // The array remains allocated, we just invalidated its contents
}

// ------------------------------------------------------------------------------------------------
aiReturn aiMaterial::RemoveProperty (const char* pKey,unsigned int type,
    unsigned int index
    )
{
    ai_assert(NULL != pKey);

    for (unsigned int i = 0; i < mNumProperties;++i) {
        aiMaterialProperty* prop = mProperties[i];

        if (prop && !strcmp( prop->mKey.data, pKey ) &&
            prop->mSemantic == type && prop->mIndex == index)
        {
            // Delete this entry
            delete mProperties[i];

            // collapse the array behind --.
            --mNumProperties;
            for (unsigned int a = i; a < mNumProperties;++a)    {
                mProperties[a] = mProperties[a+1];
            }
            return AI_SUCCESS;
        }
    }

    return AI_FAILURE;
}

// ------------------------------------------------------------------------------------------------
aiReturn aiMaterial::AddBinaryProperty (const void* pInput,
    unsigned int pSizeInBytes,
    const char* pKey,
    unsigned int type,
    unsigned int index,
    aiPropertyTypeInfo pType
    )
{
    ai_assert (pInput != NULL);
    ai_assert (pKey != NULL);
    ai_assert (0 != pSizeInBytes);

    if ( 0 == pSizeInBytes ) {

    }
    // first search the list whether there is already an entry with this key
    unsigned int iOutIndex = UINT_MAX;
    for (unsigned int i = 0; i < mNumProperties;++i)    {
        aiMaterialProperty* prop = mProperties[i];

        if (prop /* just for safety */ && !strcmp( prop->mKey.data, pKey ) &&
            prop->mSemantic == type && prop->mIndex == index){

            delete mProperties[i];
            iOutIndex = i;
        }
    }

    // Allocate a new material property
    aiMaterialProperty* pcNew = new aiMaterialProperty();

    // .. and fill it
    pcNew->mType = pType;
    pcNew->mSemantic = type;
    pcNew->mIndex = index;

    pcNew->mDataLength = pSizeInBytes;
    pcNew->mData = new char[pSizeInBytes];
    memcpy (pcNew->mData,pInput,pSizeInBytes);

    pcNew->mKey.length = ::strlen(pKey);
    ai_assert ( MAXLEN > pcNew->mKey.length);
    strcpy( pcNew->mKey.data, pKey );

    if (UINT_MAX != iOutIndex)  {
        mProperties[iOutIndex] = pcNew;
        return AI_SUCCESS;
    }

    // resize the array ... double the storage allocated
    if (mNumProperties == mNumAllocated)    {
        const unsigned int iOld = mNumAllocated;
        mNumAllocated *= 2;

        aiMaterialProperty** ppTemp;
        try {
            ppTemp = new aiMaterialProperty*[mNumAllocated];
        } catch (std::bad_alloc&) {
            delete pcNew;
            return AI_OUTOFMEMORY;
        }

        // just copy all items over; then replace the old array
        memcpy (ppTemp,mProperties,iOld * sizeof(void*));

        delete[] mProperties;
        mProperties = ppTemp;
    }
    // push back ...
    mProperties[mNumProperties++] = pcNew;
    return AI_SUCCESS;
}

// ------------------------------------------------------------------------------------------------
aiReturn aiMaterial::AddProperty (const aiString* pInput,
    const char* pKey,
    unsigned int type,
    unsigned int index)
{
    // We don't want to add the whole buffer .. write a 32 bit length
    // prefix followed by the zero-terminated UTF8 string.
    // (HACK) I don't want to break the ABI now, but we definitely
    // ought to change aiString::mLength to uint32_t one day.
    if (sizeof(size_t) == 8) {
        aiString copy = *pInput;
        uint32_t* s = reinterpret_cast<uint32_t*>(&copy.length);
        s[1] = static_cast<uint32_t>(pInput->length);

        return AddBinaryProperty(s+1,
            static_cast<unsigned int>(pInput->length+1+4),
            pKey,
            type,
            index,
            aiPTI_String);
    }
    ai_assert(sizeof(size_t)==4);
    return AddBinaryProperty(pInput,
        static_cast<unsigned int>(pInput->length+1+4),
        pKey,
        type,
        index,
        aiPTI_String);
}

// ------------------------------------------------------------------------------------------------
uint32_t Assimp::ComputeMaterialHash(const aiMaterial* mat, bool includeMatName /*= false*/)
{
    uint32_t hash = 1503; // magic start value, chosen to be my birthday :-)
    for ( unsigned int i = 0; i < mat->mNumProperties; ++i ) {
        aiMaterialProperty* prop;

        // Exclude all properties whose first character is '?' from the hash
        // See doc for aiMaterialProperty.
        if ((prop = mat->mProperties[i]) && (includeMatName || prop->mKey.data[0] != '?'))  {

            hash = SuperFastHash(prop->mKey.data,(unsigned int)prop->mKey.length,hash);
            hash = SuperFastHash(prop->mData,prop->mDataLength,hash);

            // Combine the semantic and the index with the hash
            hash = SuperFastHash((const char*)&prop->mSemantic,sizeof(unsigned int),hash);
            hash = SuperFastHash((const char*)&prop->mIndex,sizeof(unsigned int),hash);
        }
    }
    return hash;
}

// ------------------------------------------------------------------------------------------------
void aiMaterial::CopyPropertyList(aiMaterial* pcDest,
    const aiMaterial* pcSrc
    )
{
    ai_assert(NULL != pcDest);
    ai_assert(NULL != pcSrc);

    unsigned int iOldNum = pcDest->mNumProperties;
    pcDest->mNumAllocated += pcSrc->mNumAllocated;
    pcDest->mNumProperties += pcSrc->mNumProperties;

    aiMaterialProperty** pcOld = pcDest->mProperties;
    pcDest->mProperties = new aiMaterialProperty*[pcDest->mNumAllocated];

    if (iOldNum && pcOld)   {
        for (unsigned int i = 0; i < iOldNum;++i) {
            pcDest->mProperties[i] = pcOld[i];
        }
    }

    if ( pcOld ) {
        delete[] pcOld;
    }

    for (unsigned int i = iOldNum; i< pcDest->mNumProperties;++i)   {
        aiMaterialProperty* propSrc = pcSrc->mProperties[i];

        // search whether we have already a property with this name -> if yes, overwrite it
        aiMaterialProperty* prop;
        for ( unsigned int q = 0; q < iOldNum; ++q ) {
            prop = pcDest->mProperties[q];
            if (prop /* just for safety */ && prop->mKey == propSrc->mKey && prop->mSemantic == propSrc->mSemantic
                && prop->mIndex == propSrc->mIndex) {
                delete prop;

                // collapse the whole array ...
                memmove(&pcDest->mProperties[q],&pcDest->mProperties[q+1],i-q);
                i--;
                pcDest->mNumProperties--;
            }
        }

        // Allocate the output property and copy the source property
        prop = pcDest->mProperties[i] = new aiMaterialProperty();
        prop->mKey = propSrc->mKey;
        prop->mDataLength = propSrc->mDataLength;
        prop->mType = propSrc->mType;
        prop->mSemantic = propSrc->mSemantic;
        prop->mIndex = propSrc->mIndex;

        prop->mData = new char[propSrc->mDataLength];
        memcpy(prop->mData,propSrc->mData,prop->mDataLength);
    }
}
