#include "stdafx.h"
#include "AssimpUtil.h"

#include <QFileInfo>

#include <LibGeo/Path.h>
#include <sstream>

#include <C2/util/string_util.h>

#include "../FileUtil.h"



void AssimpUtil::CopyAIVerts(lib_geo::BaseMesh& mesh_dst, aiMesh* mesh)
{
	mesh_dst.m_Verts.resize(mesh->mNumVertices);
	for (unsigned int i = 0; i < mesh->mNumVertices; ++i)
	{
		const aiVector3D& v = mesh->mVertices[i];
		mesh_dst.m_Verts[i].set(v.x, v.y, v.z);
	}

	if (mesh->HasNormals())
	{
		mesh_dst.m_Normals.resize(mesh->mNumVertices);
		for (unsigned int i = 0; i < mesh->mNumVertices; ++i)
		{
			const aiVector3D& n = mesh->mNormals[i];
			mesh_dst.m_Normals[i].set(n.x, n.y, n.z);
		}
	}

	aiVector3D* tbuf = mesh->mTextureCoords[0];
	if (tbuf)
	{
		mesh_dst.m_UVs.resize(mesh->mNumVertices);
		for (unsigned int i = 0; i < mesh->mNumVertices; ++i)
		{
			const aiVector3D& v = mesh->mTextureCoords[0][i];
			mesh_dst.m_UVs[i].set(v.x, v.y);
		}
	}
}

void AssimpUtil::CopyAIFaces(lib_geo::BaseMesh& mesh_dst, aiMesh* mesh)
{
	mesh_dst.m_Faces.resize(mesh->mNumFaces);
	for (unsigned int i = 0; i < mesh->mNumFaces; ++i)
	{
		const aiFace& sf = mesh->mFaces[i];
		lib_geo::BaseFace& df = mesh_dst.m_Faces[i];

		df.m_VertIds.resize(sf.mNumIndices);
		for (unsigned int k = 0; k < sf.mNumIndices; ++k)
		{
			df.m_VertIds[k] = sf.mIndices[k];
		}

		if (mesh_dst.HasUV())
			df.m_UVIds = df.m_VertIds;

		if (mesh_dst.HasNormal())
			df.m_NormIds = df.m_VertIds;

		df.m_MatIdx = mesh->mMaterialIndex;
	}
}

lib_graph::color4f AssimpUtil::AIToColor(aiMaterialProperty* prop)
{
	lib_graph::color4f col;

	int elems = prop->mDataLength / sizeof(float);
	float* val = (float*)prop->mData;
	if (elems >= 1)
		col.r() = val[0];
	if (elems >= 2)
		col.g() = val[1];
	if (elems >= 3)
		col.b() = val[2];

	if (elems >= 4)
		col.a() = val[3];
	else
		col.a() = 1.0f;

	return col;
}

std::string AssimpUtil::GetTextureNameFromFilePath(const std::string& filepath)
{
	QString path_qs = QString::fromLocal8Bit(filepath.c_str());
	QString name_qs = QFileInfo(path_qs).fileName();
	return name_qs.toLocal8Bit().data();
}

void AssimpUtil::CopyMaterials(MeshBuf* mbuf, const aiScene* ai_scene, SceneMain& scene, const std::string& dirpath)
{
	if (!ai_scene->HasMaterials())
		return;

	lib_geo::BaseMesh& mesh_dst = mbuf->m_Mesh;

	mesh_dst.m_Materials.resize(ai_scene->mNumMaterials);
	mbuf->CreateTextureBuf(ai_scene->mNumMaterials);
	for (unsigned int i = 0; i < ai_scene->mNumMaterials; ++i)
	{
		lib_geo::BaseMaterial& mat = mesh_dst.m_Materials[i];

		aiMaterial* m = ai_scene->mMaterials[i];
		for (unsigned int j = 0; j < m->mNumProperties; ++j)
		{
			aiMaterialProperty* prop = m->mProperties[j];
			if (prop->mKey == aiString("?mat.name"))
			{
				mat.m_Name = ((aiString*)prop->mData)->data;
			}
			else if (prop->mKey == aiString("$clr.ambient"))
			{
				mat.m_Ambient = AIToColor(prop);
			}
			else if (prop->mKey == aiString("$clr.diffuse"))
			{
				mat.m_Diffuse = AIToColor(prop);
			}
			else if (prop->mKey == aiString("$clr.specular"))
			{
				mat.m_Specular = AIToColor(prop);
			}
			else if (prop->mKey == aiString("$mat.shininess"))
			{
				mat.m_Shininess = ((float*)prop->mData)[0];
			}
			else if (prop->mKey == aiString("$tex.file"))
			{
				aiString* ai_filepath = (aiString*)prop->mData;
				std::string filepath;
				filepath += dirpath;
				filepath += "\\";
				filepath += ai_filepath->data;
				const std::string name = GetTextureNameFromFilePath(filepath);

				mbuf->InitColorTexture(i, filepath, name, scene.m_TexConfig);
			}
		}
	}
}

void AssimpUtil::CreateBoneTree(NodeMap& nodemap, SceneNode* bn)
{
	if (bn == NULL)
		return;

	nodemap.Bones[bn->m_Name] = bn;

	for (size_t i = 0; i < bn->m_Children.size(); ++i)
	{
		CreateBoneTree(nodemap, &bn->m_Children[i]);
	}
}

int AssimpUtil::GetNumKeyOfFrame(const aiNodeAnim* ch)
{
	int num_keys = ch->mNumPositionKeys;
	return num_keys;
}


namespace ae
{


void ConvertVec(lm::vec3f& dst, const aiVector3D& src)
{
	dst.x = src.x;
	dst.y = src.y;
	dst.z = src.z;
}

void ConvertQuat(lm::quat4f& dst, const aiQuaternion& src)
{
	dst.x = src.x;
	dst.y = src.y;
	dst.z = src.z;
	dst.w = src.w;
}

void ConvertMat(lm::matrix4f& lm, const aiMatrix4x4& am)
{
	lm(0, 0) = am.a1;
	lm(0, 1) = am.a2;
	lm(0, 2) = am.a3;
	lm(0, 3) = am.a4;
	lm(1, 0) = am.b1;
	lm(1, 1) = am.b2;
	lm(1, 2) = am.b3;
	lm(1, 3) = am.b4;
	lm(2, 0) = am.c1;
	lm(2, 1) = am.c2;
	lm(2, 2) = am.c3;
	lm(2, 3) = am.c4;
	lm(3, 0) = am.d1;
	lm(3, 1) = am.d2;
	lm(3, 2) = am.d3;
	lm(3, 3) = am.d4;
	lm.transpose();
}

void AiQuatToLmQuat(lm::quat4f& lq, const aiQuaternion& aq)
{
	lq.x = aq.x;
	lq.y = aq.y;
	lq.z = aq.z;
	lq.w = aq.w;
}


}
