#pragma once

#include <iostream>
#include <vector>
#include <string>

#include <C2/lm/Vector2.h>
#include <C2/lm/Vector3.h>

#include <C2/graph/Color.h>


namespace lib_geo
{


class BaseMesh;


// ---------------------------------------------------------------------------------------------
// Mqo基本型
typedef lm::vector3f MqoVector;

typedef lm::vector2f MqoUV;
typedef std::vector<MqoUV> MqoUVs;


// ---------------------------------------------------------------------------------------------
// MqoMaterial
struct MqoMaterial
{
public:
	MqoMaterial(void) :
			m_Diffuse(0),
			m_Ambient(0),
			m_Emission(0),
			m_Specular(0),
			m_Shininess(0),
			m_ShadeType(MQO_PHONG) // 適当. どれがデフォルトか不明.
	{}

	std::string GetTextureFilePath(void) const
	{
		// TODO : 絶対パスに対応していない
		return m_FileDirPath + m_TextureFileName;
	}

public:
	std::string m_FileDirPath;
	std::string m_Name;

	lib_graph::color4f m_BaseColor;
	float m_Diffuse;
	float m_Ambient;
	float m_Emission;
	float m_Specular;
	float m_Shininess;

	std::string m_TextureFileName;
	std::string m_AlphaTextureFileName;

	// シェーディング形式
	enum MQO_SHADETYPE
	{
		MQO_CLASSIC  ,
		MQO_CONSTANT ,
		MQO_LAMBERT  ,
		MQO_PHONG    ,
		MQO_BLINN    ,
	};
	MQO_SHADETYPE m_ShadeType;
};
typedef std::vector<MqoMaterial> MqoMaterials;



// ---------------------------------------------------------------------------------------------
// MqoFace
struct MqoFace
{
public:
	MqoFace(void)
	{
		m_MaterialIdx  = -1;
		m_NumVertex    = 0;
		m_VertexIdx[0] = m_VertexIdx[1] = m_VertexIdx[2] = m_VertexIdx[3] = -1;
	}

	size_t NumVertices(void) const
	{
		return m_NumVertex;
	}

	size_t NumTriangles(void) const
	{
		return ( ( NumVertices() < 3 ) ? 0 : NumVertices() - 2 );
	}

public:
	int    m_MaterialIdx;
	size_t m_NumVertex; // 多分 3or4. 今のところはそれ以外の値がセットされている場合は描画しない
	int    m_VertexIdx[4];
	MqoUV  m_UV[4];
};



// ---------------------------------------------------------------------------------------------
// MqoMesh
struct MqoMesh
{
public:
	void UpdateNormals(void);

public:
	std::string             m_Name;
	std::vector<MqoVector>  m_Vertices;
	std::vector<MqoVector>  m_Normals;
	std::vector<MqoFace>    m_Faces;
};



// ---------------------------------------------------------------------------------------------
// MqoObjects
struct MqoObject
{
public:
	bool Load( const std::string& filename );

	void ConvertToBaseMesh( BaseMesh& o_mesh );

public:
	MqoMaterials          m_Materials;
	std::vector<MqoMesh>  m_Meshs;
};
typedef std::vector<MqoObject> MqoObjects;



}
