#pragma once

#include "Mix/Private/Scene/Common/Mesh.h"
#include "Mix/Geometry/Sphere.h"

namespace Mix{ namespace Scene{ namespace Common{

	class ActorModel;
	class ActorNode;

	class ActorMesh : public Mix::Scene::Common::Mesh
	{
	public:
		//ボーン構造体
		struct BONE
		{
			Mix::String linkNodeName;
			Mix::Scene::Common::ActorNode* pLinkNodePtr;
			const Mix::Matrix4x4* pLinkNodeWorldMat;

			Mix::Matrix4x4 offsetMat;
			Mix::Matrix4x4 worldMat;
		};

		//不透明サブセット構造体
		struct OPACITY_SUBSET
		{
			UInt32 boneOffset;
			UInt32 boneCount;
			UInt32 vertexStart;
			UInt32 vertexCount;
			UInt32 indexStart;
			UInt32 indexCount;
		};

		//半透明サブセット構造体
		struct TRANSPARENCY_SUBSET
		{
			UInt32 boneOffset;
			UInt32 boneCount;
			UInt32 affectBoneIndex;
			UInt32 vertexStart;
			UInt32 vertexCount;
			UInt32 indexStart;
			UInt32 indexCount;
			Mix::Vector3 sortKey;
		};

		typedef Mix::STL::Vector<Mix::Memory::SECTION_SCENE, ActorMesh::OPACITY_SUBSET> OpacitySubsetList;
		typedef Mix::STL::Vector<Mix::Memory::SECTION_SCENE, ActorMesh::TRANSPARENCY_SUBSET> TransparencySubsetList;

		//描画構造体
		struct DRAW
		{
			UInt32 materialSlotIndex;
			ActorMesh::OpacitySubsetList opSubsets;
			ActorMesh::TransparencySubsetList trSubsets[Mix::Graphics::Utility::MATERIAL_TRANSPARENCY_MAX];
		};

		typedef Mix::STL::Vector<Mix::Memory::SECTION_SCENE, ActorMesh::BONE> BoneList;
		typedef Mix::STL::Vector<Mix::Memory::SECTION_SCENE, UInt32> BoneMatTable;
		typedef Mix::STL::Vector<Mix::Memory::SECTION_SCENE, const Mix::Matrix4x4*> BoneMatPtrList;
		typedef Mix::STL::Vector<Mix::Memory::SECTION_SCENE, Mix::Matrix4x4> WorldMatrixList;
		typedef Mix::STL::Vector<Mix::Memory::SECTION_SCENE, ActorMesh::DRAW> DrawTable;

	private:
		struct MM_DESC
		{
			UInt32 boneNum;
			UInt32 boneMatNum;
			UInt32 viewVolumeNum;
			UInt32 drawNum;
			UInt32 vertexStride;
			UInt32 vertexCount;
			UInt32 indexStride;
			UInt32 indexCount;
		};

		struct MM_BONE
		{
			wchar_t linkNodeName[32];
			Mix::Matrix4x4 offsetMat;
		};

		struct MM_DRAW_DESC
		{
			UInt32 slotIndex;
			UInt32 opSubsetNum;
			UInt32 trSubsetNum[Mix::Scene::MATERIAL_TRANSPARENCY_MAX];
		};

	private:
		struct VIEW_VOLUME
		{
			Mix::Vector3 pos;
			Mix::Vector3 vec;
		};

		typedef Mix::STL::Vector<Mix::Memory::SECTION_SCENE, ActorMesh::VIEW_VOLUME> ViewVolumeList;

	private:
		Boolean m_bDraw;
		const Mix::Matrix4x4* m_pWorldMat;
		ActorMesh::BoneList m_BoneList;
		ActorMesh::BoneMatTable m_BoneMatTable;
		ActorMesh::WorldMatrixList m_WorldMatrixList;
		ActorMesh::ViewVolumeList m_ViewVolumeList;
		ActorMesh::DrawTable m_DrawTable;
		Mix::Geometry::Sphere m_Bounds;

	public:
		static ActorMesh* CreateInstance( void );
		static ActorMesh* CreateInstance( Mix::Graphics::IDevice* pDevice, Mix::IO::IReader* pReader, const wchar_t* pName );

	private:
		ActorMesh( void );
		virtual ~ActorMesh( void );

	public:
		Boolean IsDraw( void ) const;
		void SetDraw( Boolean state );

		void Link( const Mix::Matrix4x4* pWorldMat );
		void Finalize( Mix::Scene::Common::ActorModel* pActorModel );

		void Update( void );
		const Mix::Geometry::Sphere& GetBounds( void ) const;

		UInt32 GetBoneCount( void ) const;

		const ActorMesh::WorldMatrixList& GetWorldMatrixList( void ) const;
		const ActorMesh::DrawTable& GetDrawTable( void ) const;

		Boolean Clone( ActorMesh** ppMesh );

		void Dispose( void );

	private:
		static const wchar_t* CREATE_FAILED;
	};

}}}
