#ifndef CLightWaveObject_h
#define CLightWaveObject_h

/*!
 	@file
 	@brief	lwoを読み込むクラス
 */

#include"../../../Setup/CompileMode.h"
#include"../../../template/Mathematics.h"
#include"../../../Graphic/Color.h"
#include"../../../Auxiliary/FileIO/CFileRead.h"

#include<vector>
#include<list>
#include<map>

namespace Maid
{
	class CLightWaveObject
	{
	public:
		void Load( const mstring& FileName );

		struct CHUNKDATA
		{
			unt32 Name;	//!<	チャンクの名前
			unt32 Pos;	//!<	先頭アドレス
			unt32 Size;	//!<	データの長さ
		};

		void Parse( CFileRead& hFile, MySTL::vector<CHUNKDATA>& ChunkList );
		void ParseSub( CFileRead& hFile, int EndPos, MySTL::vector<CHUNKDATA>& ChunkList );


		struct LAYER
		{
			typedef	MySTL::vector<POINT3DF>	PNTS;			//	頂点配列	
			typedef	RECT3DF					BBOX;			//	バウンディングボックス	
			struct POLS
			{
				enum TYPE
				{
					FACE=0,
					CURV,
					PTCH,
					MBAL,
					BONE,
				};

				typedef MySTL::vector<unt32> INDEX;

				TYPE					Type;
				MySTL::vector<INDEX>	Polygon;
			};

			struct PTAG
			{
				enum TYPE
				{
					SURF,	//	ポリゴンに適用するサーフェス名
					PART,
					SMGP,
					BONE,	//	ボーンポリゴン(==ボーンインデックス), ボーン名
					BNWT,	//	ポリゴンに適用するウェイトマップ名
				};
				TYPE	Type;	//!<	このタグのタイプ

				struct MAP
				{
					unt32 PolygonNo;
					unt32 TypeNo;
				};
				MySTL::vector<MAP>	MapList;
			};


			struct VMAP
			{
				enum TYPE
				{
					NONE,
					PICK,
					WGHT,
					MNVW,
					TXUV,
					RGB,
					RGBA,
					MORF,
					SPOT
				};

				struct DATA
				{
					MySTL::vector<float> Value;	
				};

				TYPE	Type;
				mstring Name;

				//	Map[頂点番号] でＵＶとかにアクセスできる
				MySTL::map<int,DATA>	Map;
			};

			struct VMAD
			{
				enum TYPE
				{
					NONE,
					PICK,
					WGHT,
					MNVW,
					TXUV,
					RGB,
					RGBA,
					MORF,
					SPOT
				};

				// VMAP は頂点番号が重複しないので map でもっててもいいんだけど
				// VMAP は重複する可能性があるので、配列で持つ
				struct DATA
				{
					unt32 VertexNo;			//!<	頂点番号
					unt32 PolygonNo;
					MySTL::vector<float> Value;	
				};

				TYPE	Type;
				mstring Name;
				MySTL::vector<DATA>	Map;
			};

			unt16		Index;			//	インデックス番号
			unt16		Flag;			//	このレイヤーのフラグ
			VECTOR3DF	Pivot;
			mstring		Name;			//	レイヤー名
			PNTS		PointList;		//	座標配列	
			BBOX		BoundingBox;	//	バウンディングボックス
			MySTL::vector<POLS>		Polygon;
			MySTL::vector<PTAG>		PolygonTagMapping;
			MySTL::vector<VMAP>		VertexMap;
			MySTL::vector<VMAD>		DisVertexMap;
		};

		struct SURFACE
		{
			struct COLR
			{
				COLOR_R32G32B32F	Value;
				unt32				EnvelopeNo;
			};
			struct DIFF
			{
				float	Value;
				unt32	EnvelopeNo;
			};
			struct LUMI
			{
				float	Value;
				unt32	EnvelopeNo;
			};
			struct SPEC
			{
				float	Value;
				unt32	EnvelopeNo;
			};
			struct TRAN
			{
				float	Value;
				unt32	EnvelopeNo;
			};
			struct GLOS
			{
				float	Value;
				unt32	EnvelopeNo;
			};

			struct BLOCK
			{
				struct BASE
				{
					enum TYPE
					{
						IMAP,
						PROC,
						GRAD,
						SHDR,
					};

					enum CHAN
					{
						COLR,
						DIFF,
						LUMI,
						SPEC,
						GLOS,
						REFL,
						TRAN,
						RIND,
						TRNL,
						BUMP
					};

					struct OPAC
					{
						enum TYPE
						{
							NORMAL=0,
							SUB,
							ABS,
							MUL,
							DIV,
							ALPHA,
							TEXURE,
							ADD
						};

						TYPE	Type;
						float	Value;
						unt32	EnvelopeNo;
					};


					enum AXIS
					{
						X,
						Y,
						Z
					};

					TYPE	Type;
					mstring Priority;	//!<	効果を適用する優先度
					CHAN	Channel;
					bool	IsEnable;
					bool	IsReverseColor;
					OPAC	Opacity;
					AXIS	Axis;
				};

				struct TMAP
				{
					struct CNTR
					{
						float	x,y,z;
						unt32	EnvelopeNo;
					};
					struct SIZE
					{
						float	x,y,z;
						unt32	EnvelopeNo;
					};
					struct ROTA
					{
						float	x,y,z;
						unt32	EnvelopeNo;
					};

					struct FALL
					{
						enum TYPE
						{
							BOX,	//	立方体
							BALL,	//	球
							LINER_X,//	リニアＸ
							LINER_Y,//	リニアＹ
							LINER_Z,//	リニアＺ
						};

						TYPE	Type;
						float	x,y,z;
						unt32	EnvelopeNo;
					};

					enum CSYS
					{
						LOCAL,
						WORLD
					};
					CNTR	Center;
					SIZE	Size;		
					ROTA	Rotate;		
					mstring ObjectName;
					FALL	FallOff;
					CSYS	Csys;
				};
				struct IMAP
				{
					//	BASE::IMAP用パラメーター
					enum PROJ
					{
						PLANE,
						CIRCLE,
						BALL,
						BOX,
						FRONT,
						UV
					};
					enum AXIS
					{
						X,
						Y,
						Z
					};

					struct WRAP
					{
						enum TYPE
						{
							RESET,
							REPEAT,
							MIRROR,
							EDGE
						};

						TYPE  Type;
						float Cycles;
						unt32 EnvelopeNo;
					};

					PROJ	Projection;
					AXIS	Axis;
					unt32	ImageNo;
					WRAP	WrapW;
					WRAP	WrapH;
					mstring UVMapName;
				};
				struct PROC
				{

				};

				struct GRAD
				{

				};
				struct SHDR
				{

				};
		
				BASE Base;
				TMAP TextureMap;	//	←BASE::IMAP,BASE::PROC 共用
				IMAP ImageMap;		//	←BASE::IMAP 用
				PROC Procedure;		//	←BASE::PROC 用
				GRAD Gradient;		//	←BASE::GRAD 用
				SHDR Shader;		//	←BASE::SHDR 用
			};

			mstring Name;			//!<	このサーフェイスの名前
			mstring ParentName;		//!<	親サーフェイスの名前

			COLR	Color;
			DIFF	Diffuse;
			LUMI	Ambient;
			SPEC	Specular;
			TRAN	Trans;
			GLOS	Glossiness;

			MySTL::vector<BLOCK>	BlockList;
		};

		struct CLIP
		{
			enum TYPE
			{
				NONE,
				STIL,
				ISEQ,
				ANIM,
				XREF,
				STCC
			};
			int		ID;
			TYPE	Type;
			mstring	StillImage;	//	静止画ファイル名
		};


		struct DOCUMENT
		{
			MySTL::vector<mstring>	TagList;		//!< low 内で使われている文字列
			MySTL::list<LAYER>		LayerList;		//!< レイヤーリスト
			MySTL::vector<SURFACE>	SurfaceList;	//!< サーフェイスリスト
			MySTL::vector<CLIP>		ClipList;		//!< クリップリスト
		};

		DOCUMENT	m_Document;

	private:

		void  LoadTAGS( CFileRead& hFile, const CHUNKDATA& dat, DOCUMENT& doc );
		LAYER* LoadLAYR( CFileRead& hFile, const CHUNKDATA& dat, DOCUMENT& doc );
		void  LoadPNTS( CFileRead& hFile, const CHUNKDATA& dat, LAYER& Layer );
		void  LoadBBOX( CFileRead& hFile, const CHUNKDATA& dat, LAYER& Layer );
		void  LoadPOLS( CFileRead& hFile, const CHUNKDATA& dat, LAYER& Layer );
		void  LoadPTAG( CFileRead& hFile, const CHUNKDATA& dat, LAYER& Layer );
		void  LoadVMAP( CFileRead& hFile, const CHUNKDATA& dat, LAYER& Layer );
		void  LoadVMAD( CFileRead& hFile, const CHUNKDATA& dat, LAYER& Layer );
		void  LoadSURF( CFileRead& hFile, const CHUNKDATA& dat, DOCUMENT& doc );
		void  LoadCLIP( CFileRead& hFile, const CHUNKDATA& dat, DOCUMENT& doc );

		void  LoadSubBLOK( CFileRead& hFile, const CHUNKDATA& dat, SURFACE& surf );
	};
}

#endif
