/*
---------------------------------------------------------------------------
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 Implementation of the post processing step to remove
 *        any parts of the mesh structure from the imported data.
*/


#include "RemoveVCProcess.h"
#include <assimp/postprocess.h>
#include <assimp/DefaultLogger.hpp>
#include <assimp/scene.h>

using namespace Assimp;

// ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer
RemoveVCProcess::RemoveVCProcess() :
    configDeleteFlags()
  , mScene()
{}

// ------------------------------------------------------------------------------------------------
// Destructor, private as well
RemoveVCProcess::~RemoveVCProcess()
{}

// ------------------------------------------------------------------------------------------------
// Returns whether the processing step is present in the given flag field.
bool RemoveVCProcess::IsActive( unsigned int pFlags) const
{
    return (pFlags & aiProcess_RemoveComponent) != 0;
}

// ------------------------------------------------------------------------------------------------
// Small helper function to delete all elements in a T** aray using delete
template <typename T>
inline void ArrayDelete(T**& in, unsigned int& num)
{
    for (unsigned int i = 0; i < num; ++i)
        delete in[i];

    delete[] in;
    in = NULL;
    num = 0;
}

#if 0
// ------------------------------------------------------------------------------------------------
// Updates the node graph - removes all nodes which have the "remove" flag set and the
// "don't remove" flag not set. Nodes with meshes are never deleted.
bool UpdateNodeGraph(aiNode* node,std::list<aiNode*>& childsOfParent,bool root)
{
    bool b = false;

    std::list<aiNode*> mine;
    for (unsigned int i = 0; i < node->mNumChildren;++i)
    {
        if(UpdateNodeGraph(node->mChildren[i],mine,false))
            b = true;
    }

    // somewhat tricky ... mNumMeshes must be originally 0 and MSB2 may not be set,
    // so we can do a simple comparison against MSB here
    if (!root && AI_RC_UINT_MSB == node->mNumMeshes )
    {
        // this node needs to be removed
        if(node->mNumChildren)
        {
            childsOfParent.insert(childsOfParent.end(),mine.begin(),mine.end());

            // set all children to NULL to make sure they are not deleted when we delete ourself
            for (unsigned int i = 0; i < node->mNumChildren;++i)
                node->mChildren[i] = NULL;
        }
        b = true;
        delete node;
    }
    else
    {
        AI_RC_UNMASK(node->mNumMeshes);
        childsOfParent.push_back(node);

        if (b)
        {
            // reallocate the array of our children here
            node->mNumChildren = (unsigned int)mine.size();
            aiNode** const children = new aiNode*[mine.size()];
            aiNode** ptr = children;

            for (std::list<aiNode*>::iterator it = mine.begin(), end = mine.end();
                 it != end; ++it)
            {
                *ptr++ = *it;
            }
            delete[] node->mChildren;
            node->mChildren = children;
            return false;
        }
    }
    return b;
}
#endif

// ------------------------------------------------------------------------------------------------
// Executes the post processing step on the given imported data.
void RemoveVCProcess::Execute( aiScene* pScene)
{
    DefaultLogger::get()->debug("RemoveVCProcess begin");
    bool bHas = false; //,bMasked = false;

    mScene = pScene;

    // handle animations
    if ( configDeleteFlags & aiComponent_ANIMATIONS)
    {

        bHas = true;
        ArrayDelete(pScene->mAnimations,pScene->mNumAnimations);
    }

    // handle textures
    if ( configDeleteFlags & aiComponent_TEXTURES)
    {
        bHas = true;
        ArrayDelete(pScene->mTextures,pScene->mNumTextures);
    }

    // handle materials
    if ( configDeleteFlags & aiComponent_MATERIALS && pScene->mNumMaterials)
    {
        bHas = true;
        for (unsigned int i = 1;i < pScene->mNumMaterials;++i)
            delete pScene->mMaterials[i];

        pScene->mNumMaterials = 1;
        aiMaterial* helper = (aiMaterial*) pScene->mMaterials[0];
        ai_assert(NULL != helper);
        helper->Clear();

        // gray
        aiColor3D clr(0.6f,0.6f,0.6f);
        helper->AddProperty(&clr,1,AI_MATKEY_COLOR_DIFFUSE);

        // add a small ambient color value
        clr = aiColor3D(0.05f,0.05f,0.05f);
        helper->AddProperty(&clr,1,AI_MATKEY_COLOR_AMBIENT);

        aiString s;
        s.Set("Dummy_MaterialsRemoved");
        helper->AddProperty(&s,AI_MATKEY_NAME);
    }

    // handle light sources
    if ( configDeleteFlags & aiComponent_LIGHTS)
    {
        bHas =  true;
        ArrayDelete(pScene->mLights,pScene->mNumLights);
    }

    // handle camneras
    if ( configDeleteFlags & aiComponent_CAMERAS)
    {
        bHas = true;
        ArrayDelete(pScene->mCameras,pScene->mNumCameras);
    }

    // handle meshes
    if (configDeleteFlags & aiComponent_MESHES)
    {
        bHas = true;
        ArrayDelete(pScene->mMeshes,pScene->mNumMeshes);
    }
    else
    {
        for( unsigned int a = 0; a < pScene->mNumMeshes; a++)
        {
            if( ProcessMesh( pScene->mMeshes[a]))
                bHas = true;
        }
    }


    // now check whether the result is still a full scene
    if (!pScene->mNumMeshes || !pScene->mNumMaterials)
    {
        pScene->mFlags |= AI_SCENE_FLAGS_INCOMPLETE;
        DefaultLogger::get()->debug("Setting AI_SCENE_FLAGS_INCOMPLETE flag");

        // If we have no meshes anymore we should also clear another flag ...
        if (!pScene->mNumMeshes)
            pScene->mFlags &= ~AI_SCENE_FLAGS_NON_VERBOSE_FORMAT;
    }

    if (bHas)DefaultLogger::get()->info("RemoveVCProcess finished. Data structure cleanup has been done.");
    else DefaultLogger::get()->debug("RemoveVCProcess finished. Nothing to be done ...");
}

// ------------------------------------------------------------------------------------------------
// Setup configuration properties for the step
void RemoveVCProcess::SetupProperties(const Importer* pImp)
{
    configDeleteFlags = pImp->GetPropertyInteger(AI_CONFIG_PP_RVC_FLAGS,0x0);
    if (!configDeleteFlags)
    {
        DefaultLogger::get()->warn("RemoveVCProcess: AI_CONFIG_PP_RVC_FLAGS is zero.");
    }
}

// ------------------------------------------------------------------------------------------------
// Executes the post processing step on the given imported data.
bool RemoveVCProcess::ProcessMesh(aiMesh* pMesh)
{
    bool ret = false;

    // if all materials have been deleted let the material
    // index of the mesh point to the created default material
    if ( configDeleteFlags & aiComponent_MATERIALS)
        pMesh->mMaterialIndex = 0;

    // handle normals
    if (configDeleteFlags & aiComponent_NORMALS && pMesh->mNormals)
    {
        delete[] pMesh->mNormals;
        pMesh->mNormals = NULL;
        ret = true;
    }

    // handle tangents and bitangents
    if (configDeleteFlags & aiComponent_TANGENTS_AND_BITANGENTS && pMesh->mTangents)
    {
        delete[] pMesh->mTangents;
        pMesh->mTangents = NULL;

        delete[] pMesh->mBitangents;
        pMesh->mBitangents = NULL;
        ret = true;
    }

    // handle texture coordinates
    bool b = (0 != (configDeleteFlags & aiComponent_TEXCOORDS));
    for (unsigned int i = 0, real = 0; real < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++real)
    {
        if (!pMesh->mTextureCoords[i])break;
        if (configDeleteFlags & aiComponent_TEXCOORDSn(real) || b)
        {
            delete [] pMesh->mTextureCoords[i];
            pMesh->mTextureCoords[i] = NULL;
            ret = true;

            if (!b)
            {
                // collapse the rest of the array
                for (unsigned int a = i+1; a < AI_MAX_NUMBER_OF_TEXTURECOORDS;++a)
                    pMesh->mTextureCoords[a-1] = pMesh->mTextureCoords[a];

                pMesh->mTextureCoords[AI_MAX_NUMBER_OF_TEXTURECOORDS-1] = NULL;
                continue;
            }
        }
        ++i;
    }

    // handle vertex colors
    b = (0 != (configDeleteFlags & aiComponent_COLORS));
    for (unsigned int i = 0, real = 0; real < AI_MAX_NUMBER_OF_COLOR_SETS; ++real)
    {
        if (!pMesh->mColors[i])break;
        if (configDeleteFlags & aiComponent_COLORSn(i) || b)
        {
            delete [] pMesh->mColors[i];
            pMesh->mColors[i] = NULL;
            ret = true;

            if (!b)
            {
                // collapse the rest of the array
                for (unsigned int a = i+1; a < AI_MAX_NUMBER_OF_COLOR_SETS;++a)
                    pMesh->mColors[a-1] = pMesh->mColors[a];

                pMesh->mColors[AI_MAX_NUMBER_OF_COLOR_SETS-1] = NULL;
                continue;
            }
        }
        ++i;
    }

    // handle bones
    if (configDeleteFlags & aiComponent_BONEWEIGHTS && pMesh->mBones)
    {
        ArrayDelete(pMesh->mBones,pMesh->mNumBones);
        ret = true;
    }
    return ret;
}
