#pragma once

namespace Mix{ namespace Scene{ namespace Common{

	class Model
	{
	private:
		struct MATERIAL_SLOT
		{
			Mix::StringW name;
			Mix::Scene::IMaterial* pInterface;

			MATERIAL_SLOT( const wchar_t* _pName, Mix::Scene::IMaterial* _pInterface )
			{
				name = _pName;
				pInterface = _pInterface;
			}
		};

		typedef Mix::STL::Map<Mix::Memory::SECTION_SCENE, Mix::StringW, UInt32> IndexMap;
		typedef Mix::STL::Vector<Mix::Memory::SECTION_SCENE, Model::MATERIAL_SLOT> MaterialSlotList;
		typedef Mix::STL::Vector<Mix::Memory::SECTION_SCENE, Mix::Scene::IMaterial*> MaterialPtrList;

	private:
		Model::IndexMap m_MaterialSlotIndexMap;
		Model::MaterialSlotList m_MaterialSlotList;
		Model::MaterialPtrList m_UpdateMaterialPtrList;
		Boolean m_bAttachUpdateMaterials;

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

		virtual void AttachDynamics( Mix::Dynamics::IWorld* pWorld, Mix::Dynamics::IObjectListener* pObjectListener ) = 0;
		virtual void DetachDynamics( Mix::Dynamics::IWorld* pWorld ) = 0;

		void ReserveMaterialSlots( UIntT count );
		void AddMaterialSlot( const wchar_t* pName, Mix::Scene::IMaterial* pInterface );
		Boolean CloneMaterials( Model* pModel, Boolean bShared );
		void AttachUpdateMaterials( void );
		void DetachUpdateMaterials( void );

		UInt32 GetMaterialSlotCount( void ) const;
		UInt32 GetMaterialSlotIndex( const wchar_t* pName );
		const wchar_t* GetMaterialSlotName( UInt32 index ) const;
		Boolean SetMaterialByIndex( UInt32 index, Mix::Scene::IMaterial* pInterface );
		Boolean SetMaterialByName( const wchar_t* pName, Mix::Scene::IMaterial* pInterface );
		Boolean GetMaterialByIndex( UInt32 index, Mix::Scene::IMaterial** ppInterface );
		Boolean GetMaterialByName( const wchar_t* pName, Mix::Scene::IMaterial** ppInterface );
		Mix::Scene::IMaterial* GetMaterialPtr( UInt32 index ) const;
	};

}}}
