#pragma once

#include "Mix/Private/Container.h"

class btCollisionShape;

namespace Mix{ namespace Dynamics{

	class IShape;

	class ObjectContext
	{
	private:
		enum VALUE
		{
			CONTACTLIST_DEF_CAPACITY = 16,
			CONTACTLIST_RESIZE_STEP = 4,
		};

		typedef Mix::STL::List<Mix::Memory::SECTION_DYNAMICS, Mix::Dynamics::IObjectListener*> ListenerList;

	protected:
		Mix::Dynamics::IObject* m_pOwner;
		Mix::Dynamics::MATERIAL m_Material;
		ObjectContext::ListenerList m_ListenerList;

	public:
		MIX_DECLARE_ALLOCATOR();

		ObjectContext( Mix::Dynamics::IObject* pOwner, const wchar_t* pDebugName );
		virtual ~ObjectContext( void );

		Mix::Dynamics::IObject* GetOwnerPtr( void ) const;

		Boolean IsExistsListener( void ) const;
		Boolean AddListener( Mix::Dynamics::IObjectListener* pListener );
		void RemoveListener( Mix::Dynamics::IObjectListener* pListener );

		void NotifyAddedToWorld( Mix::Dynamics::IWorld* pWorld );
		void NotifyRemovedFromWorld( Mix::Dynamics::IWorld* pWorld );
		void NotifyContact( const Mix::Dynamics::MANIFOLD& manifold );

		const Mix::Dynamics::MATERIAL& GetMaterial( void ) const;
		void SetMaterial( const Mix::Dynamics::MATERIAL& material );

		virtual const Mix::Dynamics::MATERIAL& QueryMaterial( UInt32 partIndex, UInt32 polygonIndex ) const;
	};

	class StaticMeshContext : public Mix::Dynamics::ObjectContext
	{
	private:
		Mix::STL::Vector<Mix::Memory::SECTION_DYNAMICS, Mix::STL::Vector<Mix::Memory::SECTION_DYNAMICS, UInt32>> m_Parts;
		Mix::STL::Vector<Mix::Memory::SECTION_DYNAMICS, Mix::Dynamics::MATERIAL> m_Materials;
		UInt32 m_TotalPolygonCount;

	public:
		MIX_DECLARE_ALLOCATOR();

		StaticMeshContext( Mix::Dynamics::IObject* pOwner, const wchar_t* pDebugName );
		virtual ~StaticMeshContext( void );

		void InitializeParts( UInt32 count );
		void InitializePolygonMaterialIndices( UInt32 partIndex, UInt32 polygonCount );
		void InitializeMaterials( UInt32 count );
		void InitializeFinish( void );

		UInt32 GetPartCount( void ) const;

		UInt32 GetPolygonCount( UInt32 partIndex ) const;
		UInt32 GetTotalPolygonCount( void ) const;

		UInt32 GetLocalMaterialCount( void ) const;

		UInt32 GetMaterialIndex( UInt32 partIndex, UInt32 polygonIndex ) const ;
		Boolean SetMaterialIndex( UInt32 partIndex, UInt32 polygonIdnex, UInt32 materialIndex );
		UInt32 LockMaterialIndices( UInt32 partIndex, UInt32 polygonStartIndex, UInt32 polygonCount, UInt32** ppMaterialIndices );

		const Mix::Dynamics::MATERIAL& GetLocalMaterial( UInt32 index );
		Boolean GetLocalMaterial( UInt32 index, Mix::Dynamics::MATERIAL& material );
		Boolean SetLocalMaterial( UInt32 index, const Mix::Dynamics::MATERIAL& material );
		UInt32 LockLocalMaterials( UInt32 startIndx, UInt32 count, Mix::Dynamics::MATERIAL** ppMaterials );

	public:
		virtual const Mix::Dynamics::MATERIAL& QueryMaterial( UInt32 partIndex, UInt32 polygonIndex ) const;
	};

}}
