#pragma once

namespace Mix{ namespace Graphics{ namespace Common{
	class Manager;
}}}

namespace Mix{ namespace Scene{ namespace Common{

	class EffectPackage;
	class ActorMesh;
	class ActorModel;
	class ActorKinematicCharacter;
	class ActorCollider;
	class ActorSensor;

	class ActorLoader
	{
	private:
		//MAM定数
		enum MAM_VALUE
		{
			//ファイルヘッダ
			MAM_MAGICNUMBER = 0x464D414D,
			MAM_VERSION = 0x01000000,

			//メインフレーム : 座標系
			MAM_CS_LH = 1,
			MAM_CS_RH = 2,

			//シェイプ
			MAM_BOX_SHAPE		= 1,
			MAM_CAPSULE_SHAPE	= 2,
			MAM_SPHERE_SHAPE	= 3,

			//軸
			MAM_AXIS_X = 1,
			MAM_AXIS_Y = 2,
			MAM_AXIS_Z = 3,

			//コライダー(ステータス)
			MAM_CS_DEFAULT			= 1,
			MAM_CS_STATIC			= 2,
			MAM_CS_KINEMATIC		= 3,

			//コライダー(フラグ)
			MAM_CF_ROT_X			= 0x00000001,
			MAM_CF_ROT_Y			= 0x00000002,
			MAM_CF_ROT_Z			= 0x00000004,
			MAM_CF_ALWAYS_ACTIVE	= 0x00000008,
			MAM_CF_CAST_MOTION		= 0x00000010,

			//ジョイント(タイプ)
			MAM_POINT_JOINT	= 1,
			MAM_HINGE_JOINT	= 2,
			MAM_BALL_JOINT	= 3,

			//ジョイント(フラグ)
			MAM_JF_COLLISION_DISABLED = 0x00000001,
		};

		//MAMファイルヘッダ構造体
		struct MAM_FILE_HEADER_1_0_0_0
		{
			UInt32 magicNumber;
			UInt32 version;
		};

		//MAMデータヘッダ構造体
		struct MAM_DATA_HEADER_1_0_0_0
		{
			UInt32 materialNum;
			UInt32 meshNum;
			UInt32 motionControllerNum;
			UInt32 kinematicCharacterNum;
			UInt32 shapeNum;
			UInt32 colliderNum;
			UInt32 sensorNum;
			UInt32 jointNum;
			UInt32 mainFrameNum;
			UInt32 nodeNum;
		};

		//MAMモーションコントローラー構造体
		struct MAM_MOTION_CONTROLLER_1_0_0_0
		{
			wchar_t name[32];
			UInt32 priority;
			UInt32 motionNum;
		};

		//MAMキネマティックキャラクター構造体
		struct MAM_KINEMATIC_CHARACTER_1_0_0_0
		{
			Mix::Matrix4x4 loadMat;
			Mix::Matrix4x4 storeMat;
			float height;
			float radius;
			float garvity;
			float maxFallSpeed;
			float initJumpSpeed;
			float stepHeight;
			float slopeLimit;
			unsigned int reserve;
		};

		//MAMシェイプ構造体
		struct MAM_SHAPE_1_0_0_0
		{
			Mix::Quaternion localRotation;
			Mix::Vector4 localPosition;
			unsigned int type;
			unsigned int data[5];
		};

		//MAMボックスシェイプ構造体
		struct MAM_BOX_SHAPE_DATA_1_0_0_0
		{
			Mix::Vector3 halfExtents;

			unsigned int reserve[2];
		};

		//MAMカプセルシェイプ構造体
		struct MAM_CAPSULE_SHAPE_DATA_1_0_0_0
		{
			unsigned int axis;
			float length;
			float radius;

			unsigned int reserve[2];
		};

		//MAMスフィアシェイプ構造体
		struct MAM_SPHERE_SHAPE_DATA_1_0_0_0
		{
			float radius;

			unsigned int reserve[4];
		};

		//MAMコライダー構造体
		struct MAM_COLLIDER_1_0_0_0
		{
			wchar_t name[32];
			unsigned int shapeNum;
			unsigned int id;
			unsigned int attr;
			float friction;
			float restitution;
			unsigned int status;
			float mass;
			unsigned int flags;
			Mix::Matrix4x4 centerMatrix;
			Mix::Matrix4x4 restoreMatrix;
			Mix::Quaternion rotation;
			Mix::Vector4 position;
		};

		//MAMセンサー構造体
		struct MAM_SENSOR_1_0_0_0
		{
			wchar_t name[32];
			unsigned int shapeNum;
			unsigned int id;
			unsigned int attr;
			unsigned int reserve;
			Mix::Matrix4x4 centerMatrix;
			Mix::Quaternion rotation;
			Mix::Vector4 position;
		};

		//MAMジョイント構造体
		struct MAM_JOINT_1_0_0_0
		{
			unsigned int type;
			unsigned int flags;
			int colliderA;
			int colliderB;
			Mix::Vector4 pivotA;
			Mix::Vector4 pivotB;
			Mix::Matrix4x4 localPivotB;
			unsigned int data[16];
		};

		//MAMポイントジョイント構造体
		struct MAM_POINT_JOINT_DATA_1_0_0_0
		{
			float pivotSpring;
			float pivotDamper;
			unsigned int reserve[14];
		};

		//MAMヒンジジョイント構造体
		struct MAM_HINGE_JOINT_DATA_1_0_0_0
		{
			Mix::Vector4 axis;
			float lowerLimit;
			float upperLimit;
			float limitSpring;
			float limitDamper;
			unsigned int reserve[8];
		};

		//MAMボールジョイント構造体
		struct MAM_BALL_JOINT_DATA_1_0_0_0
		{
			Mix::Vector4 twistAxis;
			Mix::Vector4 swingAxis;
			float twistLimit;
			float swingLimit1;
			float swingLimit2;
			float pivotSpring;
			float pivotDamper;
			float limitSpring;
			float limitDamper;
			unsigned int reserve;
		};

		//MAMメインフレーム構造体
		struct MAM_MAIN_FRAME_1_0_0_0
		{
			Mix::Vector4 scaling;
			Mix::Quaternion rotation;
			Mix::Vector4 translation;
			UInt32 coordinateSystem;
			UInt32 colliderNum;
			UInt32 sensorNum;
			UInt32 reserve;
			Mix::Matrix4x4 receiveMotionMatrix;
		};

		//MAMノード構造体
		struct MAM_NODE_1_0_0_0
		{
			wchar_t name[32];

			Mix::Vector4 geometricS;
			Mix::Quaternion geometricR;
			Mix::Vector4 geometricT;

			Mix::Vector4 localS;
			Mix::Quaternion localR;
			Mix::Vector4 localT;

			Int32 meshIndex;

			UInt32 colliderNum;
			UInt32 sensorNum;
			UInt32 jointNum;

			Int32 parent;
			Int32 childCount;
		};

		struct SHAPE
		{
			Mix::Quaternion localRot;
			Mix::Vector3 localPos;
			Mix::Dynamics::IShape* ptr;
		};

		struct JOINT
		{
			Boolean bCollisionDisabled;
			Mix::Matrix4x4 localPivotB;
			Mix::Dynamics::IJoint* ptr;

			JOINT( Boolean _bCollisionDisabled, const Mix::Matrix4x4& _localPivotB, Mix::Dynamics::IJoint* _ptr )
			{
				bCollisionDisabled = _bCollisionDisabled;
				localPivotB = _localPivotB;
				ptr = _ptr;
			}
		};

		typedef Mix::STL::Vector<Mix::Memory::SECTION_SCENE, Mix::Scene::Common::ActorMesh*> MeshList;
		typedef Mix::STL::Vector<Mix::Memory::SECTION_SCENE, UInt8> Buffer;
		typedef Mix::STL::Vector<Mix::Memory::SECTION_SCENE, ActorLoader::SHAPE> ShapeList;
		typedef Mix::STL::Vector<Mix::Memory::SECTION_SCENE, Mix::Scene::Common::ActorCollider*> ColliderList;
		typedef Mix::STL::Vector<Mix::Memory::SECTION_SCENE, Mix::Scene::Common::ActorSensor*> SensorList;
		typedef Mix::STL::Vector<Mix::Memory::SECTION_SCENE, ActorLoader::JOINT> JointList;

	private:
		Mix::Dynamics::IManager* m_pDynamicsManager;
		Mix::Graphics::IDevice* m_pGraphicsDevice;

		ActorLoader::MeshList m_MeshList;
		ActorLoader::ShapeList m_ShapeList;
		ActorLoader::ColliderList m_ColliderList;
		ActorLoader::SensorList m_SensorList;
		ActorLoader::JointList m_JointList;
		Mix::Scene::Common::ActorKinematicCharacter* m_pKinematicCharacter;

		ActorLoader::Buffer m_TempBuffer;

	private:
		Boolean Create( Mix::Scene::Common::EffectPackage* pEffectPackage, Mix::IO::IReader* pReader, Mix::Scene::Common::ActorModel* pModel );

	public:
		ActorLoader( void );
		virtual ~ActorLoader( void );

		Mix::Scene::IActorModel* Create( Mix::Scene::Common::EffectPackage* pEffectPackage, Mix::IO::IReader* pReader );

	public:
		static const wchar_t* FAILED_CREATE;
	};

}}}
