#pragma once

#include "Mix/Tool/CLR/Core/Utility/BindingItem.h"

using namespace System::ComponentModel;

namespace Mix{ namespace Tool{ namespace Utility{
	ref class NamingService;
}}}

namespace Mix{ namespace Tool{ namespace Dynamics{

	ref class IdentifierGenerator;
	ref class FlagsGenerator;
	ref class PhysicsMaterial;

	public ref class PhysicsMaterial : public System::ComponentModel::INotifyPropertyChanged
	{
	public:
		static const int DefaultIdentifier = 0;
		static const int DefaultAttributes = 0;
		static const float DefaultFriction = 0.5f;
		static const float DefaultRestitution = 0.0f;

	private:
		Mix::Tool::Utility::NamingService^ m_NamingService;
		System::String^ m_Name;
		System::String^ m_ImageFilePath;
		System::Drawing::Image^ m_Image;
		Mix::Tool::Dynamics::IdentifierGenerator^ m_Ident;
		Mix::Tool::Dynamics::FlagsGenerator^ m_Attr;
		float m_Friction;
		float m_Restitution;
		bool m_bIsDisposed;

	internal:
		PhysicsMaterial(	Mix::Tool::Utility::NamingService^ namingService,
							Mix::Tool::Utility::BindingItemCollection<int>^ identList,
							Mix::Tool::Utility::BindingItemCollection<int>^ attrList );

		PhysicsMaterial(	Mix::Tool::Utility::NamingService^ namingService,
							Mix::Tool::Utility::BindingItemCollection<int>^ identList,
							Mix::Tool::Utility::BindingItemCollection<int>^ attrList,
							System::String^ name );

		~PhysicsMaterial( void );

		void NotifyDisposing( void );

	public:
		event System::EventHandler^ ValueChanged;
		event System::EventHandler^ Disposing;

		property System::String^ Name
		{
			System::String^ get( void );
			void set( System::String^ value );
		}

		property System::String^ ImageFilePath
		{
			System::String^ get( void );
			void set( System::String^ value );
		}

		property System::Drawing::Image^ Image
		{
			System::Drawing::Image^ get( void );
		}

		property Mix::Tool::Dynamics::IdentifierGenerator^ Identifier
		{
			Mix::Tool::Dynamics::IdentifierGenerator^ get( void );
		}

		property Mix::Tool::Dynamics::FlagsGenerator^ Attributes
		{
			Mix::Tool::Dynamics::FlagsGenerator^ get( void );
		}

		property float Friction
		{
			float get( void );
			void set( float value );
		}

		property float Restitution
		{
			float get( void );
			void set( float value );
		}
/*
		[Browsable( false )]
		property Mix::Tool::Dynamics::PhysicsMaterial^ Value
		{
			Mix::Tool::Dynamics::PhysicsMaterial^ get( void );
		}
*/
		[Browsable( false )]
		property bool IsDisposed
		{
			bool get( void );
		}

		virtual event System::ComponentModel::PropertyChangedEventHandler^ PropertyChanged;

	private:
		void LoadImage( void );
		void UnloadImage( void );

		void IdentifierChanged( System::Object^ sender, System::EventArgs^ e );
		void AttributesChanged( System::Object^ sender, System::EventArgs^ e );

		void NotifyValueChanged( void );
		void NotifyPropertyChanged( System::String^ propertyName );
	};

	public ref class PhysicsMaterialCollection : public System::Collections::Generic::IEnumerable<Mix::Tool::Dynamics::PhysicsMaterial^>
	{
	private:
		Mix::Tool::Utility::NamingService^ m_NamingService;
		Mix::Tool::Utility::BindingItemCollection<int>^ m_IdentList;
		Mix::Tool::Utility::BindingItemCollection<int>^ m_AttrList;
		System::ComponentModel::BindingList<Mix::Tool::Dynamics::PhysicsMaterial^>^ m_List;

	public:
		PhysicsMaterialCollection(	Mix::Tool::Utility::BindingItemCollection<int>^ identList,
									Mix::Tool::Utility::BindingItemCollection<int>^ attrList );

		~PhysicsMaterialCollection( void );

		property int Count
		{
			int get( void );
		}

		property Mix::Tool::Dynamics::PhysicsMaterial^ default[int]
		{
			Mix::Tool::Dynamics::PhysicsMaterial^ get( int index );
		}

		property Mix::Tool::Dynamics::PhysicsMaterial^ default[System::String^]
		{
			Mix::Tool::Dynamics::PhysicsMaterial^ get( System::String^ name );
		}

		property System::ComponentModel::BindingList<Mix::Tool::Dynamics::PhysicsMaterial^>^ DataSource
		{
			System::ComponentModel::BindingList<Mix::Tool::Dynamics::PhysicsMaterial^>^ get( void );
		}

		Mix::Tool::Dynamics::PhysicsMaterial^ Add( void );
		Mix::Tool::Dynamics::PhysicsMaterial^ Add( System::String^ name );
		bool Remove( Mix::Tool::Dynamics::PhysicsMaterial^ physicsMaterial );
		void Clear( void );
		int IndexOf( System::String^ name );

	public:
		virtual System::Collections::IEnumerator^ GetEnumerator( void );
		virtual System::Collections::Generic::IEnumerator<Mix::Tool::Dynamics::PhysicsMaterial^>^ GetEnumerator_Generic( void ) = System::Collections::Generic::IEnumerable<Mix::Tool::Dynamics::PhysicsMaterial^>::GetEnumerator;
	};

}}}
