#include "stdafx.h"
#include "PmdLoader.h"

#include <LibQtGeoViewerCore/SceneMain.h>

#include "../FileUtil.h"

#include <meshio/pmd.h>

#include <C2/util/string_util.h>
#include <LibGeo/Path.h>

#include <boost/algorithm/string.hpp>



bool PmdLoader::Load(SceneMain& scene, const std::string& filename)
{
	meshio::pmd::IO pm;
	if (!pm.read(filename.c_str()))
		return false;

	GeomObject* geom = scene.CreateNewGeometry();
	MeshBuf* mbuf = geom->CreateNewMeshBuf();
	scene.RefreshObjectIndex();

	lib_geo::BaseMesh& m = mbuf->m_Mesh;
	m.m_Verts.reserve(pm.vertices.size());
	m.m_Normals.reserve(pm.vertices.size());
	m.m_UVs.reserve(pm.vertices.size());
	for (const meshio::pmd::Vertex& pv : pm.vertices)
	{
		const meshio::Vector3& p = pv.pos;
		const meshio::Vector3& n = pv.normal;
		const meshio::Vector2& t = pv.uv;
		m.m_Verts.push_back(lm::vec3f(p.x, p.y, p.z));
		m.m_Normals.push_back(lm::vec3f(n.x, n.y, n.z));
		m.m_UVs.push_back(lm::vec2f(t.x, t.y));
	}

	size_t num_face = pm.indices.size() / 3;
	m.m_Faces.resize(num_face);
	for (size_t i = 0; i < num_face; ++i)
	{
		lib_geo::BaseFace& df = m.m_Faces[i];
		df.m_VertIds.resize(3);
		df.m_VertIds[0] = pm.indices[i * 3 + 0];
		df.m_VertIds[1] = pm.indices[i * 3 + 1];
		df.m_VertIds[2] = pm.indices[i * 3 + 2];
		df.m_NormIds = df.m_VertIds;
		df.m_UVIds = df.m_VertIds;
	}

	std::string dir = lib_geo::Path::GetParentDirPath(filename);
	m.m_Materials.resize(pm.materials.size());
	mbuf->CreateTextureBuf(pm.materials.size());
	for (size_t i = 0; i < pm.materials.size(); ++i)
	{
		const meshio::pmd::Material& sm = pm.materials[i];
		lib_geo::BaseMaterial& dm = m.m_Materials[i];
		dm.m_Ambient.set(sm.ambient.r, sm.ambient.g, sm.ambient.b, 1.0f);
		dm.m_Diffuse.set(sm.diffuse.r, sm.diffuse.g, sm.diffuse.b, sm.diffuse.a);
		dm.m_Specular.set(sm.specular.r, sm.specular.g, sm.specular.b, 1.0f);
		dm.m_Shininess = sm.shinness;

		std::string tex = sm.texture.str();
		std::vector<std::string> texlist;
		util::String::Split(tex, texlist, '*');

		for (const std::string& texfile : texlist)
		{
			std::string path = dir + texfile;
			std::string::size_type p = path.find_last_of('.');
			if (p == std::string::npos)
				continue;

			std::string ext = path.substr(p);
			boost::algorithm::to_lower(ext);
			if (ext != ".png" &&
				ext != ".bmp" &&
				ext != ".jpg" &&
				ext != ".jpeg" &&
				ext != ".tga")
				continue;

			mbuf->InitColorTexture(i, path, texfile, scene.m_TexConfig);
			break;
		}

		std::ostringstream ss;
		ss << "mat_" << i;
		dm.m_Name = ss.str();
	}

	int vs_idx = 0;
	for (size_t i = 0; i < pm.materials.size(); ++i)
	{
		int vd = vs_idx + pm.materials[i].vertex_count;

		int vs = vs_idx;
		vs_idx = vd;

		vs /= 3;
		vd /= 3;

		for (int j = vs; j < vd; ++j)
		{
			m.m_Faces[j].m_MatIdx = (int)i;
		}
	}

	geom->m_Name = FileUtil::GetFileTitle(filename);

	geom->m_FileFormat = GeomFileFormat::Pmd;
	geom->m_FilePath = filename;
	geom->InitializeBufferCommon();
	scene.UpdateTransform();

	scene.ReportDoneEditGeometry();

	return true;
}
