#include "UnitTestPCH.h"

#include <assimp/scene.h>
#include <RemoveRedundantMaterials.h>
#include <MaterialSystem.h>


using namespace std;
using namespace Assimp;

class RemoveRedundantMatsTest : public ::testing::Test
{
public:

	virtual void SetUp();
	virtual void TearDown();

protected:

	RemoveRedundantMatsProcess* piProcess;

	aiScene* pcScene1;
	aiScene* pcScene2;
};

// ------------------------------------------------------------------------------------------------
aiMaterial* getUniqueMaterial1()
{
	// setup an unique name for each material - this shouldn't care
	aiString mTemp;
	mTemp.Set("UniqueMat1");

	aiMaterial* pcMat = new aiMaterial();
	pcMat->AddProperty(&mTemp,AI_MATKEY_NAME);
	float f = 2.0f;
	pcMat->AddProperty<float>(&f, 1, AI_MATKEY_BUMPSCALING);
	pcMat->AddProperty<float>(&f, 1, AI_MATKEY_SHININESS_STRENGTH);
	return pcMat;
}

// ------------------------------------------------------------------------------------------------
aiMaterial* getUniqueMaterial2()
{
	// setup an unique name for each material - this shouldn't care
	aiString mTemp;
	mTemp.Set("Unique Mat2");

	aiMaterial* pcMat = new aiMaterial();
	pcMat->AddProperty(&mTemp,AI_MATKEY_NAME);
	float f = 4.0f;int i = 1;
	pcMat->AddProperty<float>(&f, 1, AI_MATKEY_BUMPSCALING);
	pcMat->AddProperty<int>(&i, 1, AI_MATKEY_ENABLE_WIREFRAME);
	return pcMat;
}

// ------------------------------------------------------------------------------------------------
aiMaterial* getUniqueMaterial3()
{
	// setup an unique name for each material - this shouldn't care
	aiString mTemp;
	mTemp.Set("Complex material name");

	aiMaterial* pcMat = new aiMaterial();
	pcMat->AddProperty(&mTemp,AI_MATKEY_NAME);
	return pcMat;
}

// ------------------------------------------------------------------------------------------------
void RemoveRedundantMatsTest::SetUp()
{
	// construct the process
	piProcess = new RemoveRedundantMatsProcess();

	// create a scene with 5 materials (2 is a duplicate of 0, 3 of 1)
	pcScene1 = new aiScene();
	pcScene1->mNumMaterials = 5;
	pcScene1->mMaterials = new aiMaterial*[5];

	pcScene1->mMaterials[0] = getUniqueMaterial1();
	pcScene1->mMaterials[1] = getUniqueMaterial2();
	pcScene1->mMaterials[4] = getUniqueMaterial3();

	// all materials must be referenced
	pcScene1->mNumMeshes = 5;
	pcScene1->mMeshes = new aiMesh*[5];
	for (unsigned int i = 0; i < 5;++i)	{
		pcScene1->mMeshes[i] = new aiMesh();
		pcScene1->mMeshes[i]->mMaterialIndex = i;
	}

	// setup an unique name for each material - this shouldn't care
	aiString mTemp;
	mTemp.length = 1;
	mTemp.data[0] = 48;
	mTemp.data[1] = 0;

	aiMaterial* pcMat;
	pcScene1->mMaterials[2] = pcMat = new aiMaterial();
	aiMaterial::CopyPropertyList(pcMat,(const aiMaterial*)pcScene1->mMaterials[0]);
	pcMat->AddProperty(&mTemp,AI_MATKEY_NAME);
	mTemp.data[0]++;

	pcScene1->mMaterials[3] = pcMat = new aiMaterial();
	aiMaterial::CopyPropertyList(pcMat,(const aiMaterial*)pcScene1->mMaterials[1]);
	pcMat->AddProperty(&mTemp,AI_MATKEY_NAME);
	mTemp.data[0]++;
}

// ------------------------------------------------------------------------------------------------
void RemoveRedundantMatsTest::TearDown()
{
	delete piProcess;
	delete pcScene1;
}

// ------------------------------------------------------------------------------------------------
TEST_F(RemoveRedundantMatsTest, testRedundantMaterials)
{
	piProcess->SetFixedMaterialsString();

	piProcess->Execute(pcScene1);
	EXPECT_EQ(3U, pcScene1->mNumMaterials);
	EXPECT_TRUE(0 != pcScene1->mMaterials &&
		0 != pcScene1->mMaterials[0] &&
		0 != pcScene1->mMaterials[1] &&
		0 != pcScene1->mMaterials[2]);

	aiString sName;
	EXPECT_EQ(AI_SUCCESS, aiGetMaterialString(pcScene1->mMaterials[2],AI_MATKEY_NAME,&sName));
	EXPECT_STREQ("Complex material name", sName.data);

}

// ------------------------------------------------------------------------------------------------
TEST_F(RemoveRedundantMatsTest, testRedundantMaterialsWithExcludeList)
{
	piProcess->SetFixedMaterialsString("\'Unique Mat2\'\t\'Complex material name\' and_another_one_which_we_wont_use");

	piProcess->Execute(pcScene1);
	EXPECT_EQ(4U, pcScene1->mNumMaterials);
	EXPECT_TRUE(0 != pcScene1->mMaterials &&
		0 != pcScene1->mMaterials[0] &&
		0 != pcScene1->mMaterials[1] &&
		0 != pcScene1->mMaterials[2] &&
		0 != pcScene1->mMaterials[3]);

	aiString sName;
	EXPECT_EQ(AI_SUCCESS, aiGetMaterialString(pcScene1->mMaterials[3],AI_MATKEY_NAME,&sName));
	EXPECT_STREQ("Complex material name", sName.data);
}