#pragma once

#include <vector>

#include <C2/lm/vector2.h>
#include <C2/lm/vector3.h>
#include <C2/lm/range3.h>

#include <C2/graph/material.h>



namespace lib_geo
{


class BaseEdge;
class BaseFace;
class VertAdj;
class BaseMesh;



//! 基本エッジ
class BaseEdge
{
public:
	BaseEdge(void)
	{
		m_VertIds[0] = -1;
		m_VertIds[1] = -1;
	}

	virtual void Clear(void);
	virtual void ClearAdjBuffer(void);

	bool IsBound(void) const;

public:
	int               m_VertIds[2];

	std::vector<int>  m_AdjFids;
};


//! 基本ポリゴン
class BaseFace
{
public:
	BaseFace(void)
		: m_MatIdx(-1)
	{}

	virtual void Clear(void);
	virtual void ClearAdjBuffer(void);
	virtual void ClearMatIdx(void);

	//! 頂点数を取得する.
	size_t NumVertices(void) const;
	//! 三角化したときの三角形の枚数を取得する.
	size_t NumTriangles(void) const;

	// 位置以外の要素を持っているか確認する.
	bool HasNormal(void) const;
	bool HasUV(void) const;

	//! 要素数に異常が無いか検証する
	bool VerifyElementCounts(void) const;

	bool HasValidMatIdx(void) const { return m_MatIdx != -1; }

	void CopySubTriangle(BaseFace& f, int lvid0, int lvid1, int lvid2) const;

public:
	std::vector<int>  m_VertIds; //!< 頂点インデックス
	std::vector<int>  m_NormIds; //!< 頂点にバインドされた法線インデックス
	std::vector<int>  m_UVIds;   //!< 頂点にバインドされたUVインデックス

	std::vector<int>  m_AdjEids;

	int               m_MatIdx;  //!< ポリゴンの個別マテリアルインデックス. 未指定 => -1
};


//! 頂点の隣接情報
class VertAdj
{
public:
	VertAdj(void)
	{}

	virtual void ClearAdjBuffer(void);


public:
	std::vector<int>  m_AdjEids;
	std::vector<int>  m_AdjFids;

	lm::vec3f m_NormalAvg;
};


class BasePolyline
{
public:
	void Clear(void);

	void Swap(BasePolyline& pl);

public:
	std::vector<int> m_VertIds;
};


class BaseMaterial : public lib_graph::Material
{
public:
	BaseMaterial(void) : lib_graph::Material() {}
	BaseMaterial(const lib_graph::Material& m) : lib_graph::Material(m) {}

	void operator=(const lib_graph::Material& m)
	{
		(*dynamic_cast<lib_graph::Material*>(this)) = m;
	}

	std::string m_Name;
};


}
