#pragma once

#include <string>
#include <vector>

#include "Mix/Tool/Win32/Core/Object.h"
#include "Mix/Tool/Win32/Core/File/InputStream.h"
#include "Mix/Tool/Win32/Core/File/OutputStream.h"
#include "Mix/Tool/Win32/Core/Graphics/ObjectModel.h"

namespace Mix{ namespace Tool{ namespace Win32{ namespace Graphics{

	class MotionController;
	class MotionCurve;
	class RootMotionCurve;

	class Motion : public Mix::Tool::Win32::Object
	{
	private:
		static const wchar_t* DEF_NAME;
		static const wchar_t* FILE_EXT;

		enum MOT_VALUE
		{
			MOT_MAGIC_NUMBER = 0x5F544F4D,
			MOT_VERSION = 0x01000000,
		};

		struct MOT_FILE_HEADER
		{
			unsigned int magicNumber;
			unsigned int version;
		};

		struct MOT_DATA_HEADER
		{
			wchar_t name[32];
			float framesPerSec;
			float lastFrame;
			float speed;
			float blendRatio;
			float loopStartFrame;
			float loopEndFrame;
			unsigned int rtCurveNum;
			unsigned int btCurveNum;
		};

		typedef std::vector<Mix::Tool::Win32::Graphics::MotionCurve*> CurveList;

	private:
		Mix::Tool::Win32::Graphics::ObjectModel* m_pObjectModel;
		Mix::Tool::Win32::Graphics::MotionController* m_pController;

		std::wstring m_DefaultName;
		std::wstring m_Name;

		std::wstring m_SaveFilePath;

		bool m_bDefault;

		float m_Speed;
		float m_BlendRatio;

		float m_FramesPerSec;
		float m_LastTime;

		float m_LoopStartTime;
		float m_LoopEndTime;

		bool m_bLoop;

		Motion::CurveList m_CurveList;

		unsigned int m_RTFlags;
		Mix::Tool::Win32::Graphics::RootMotionCurve* m_pRTCurve;

	private:
		Motion( Mix::Tool::Win32::Graphics::ObjectModel* pObjectModel, float framesPerSec );
		~Motion( void );

		void SetController( Mix::Tool::Win32::Graphics::MotionController* pSubject );
		void Release( void );

		void SetDefaultName( const wchar_t* pName );

		D3DXQUATERNION ConvertRootRotationAxis( const D3DXQUATERNION& rotation, const MOTION_RT_AXIS& axis );
		D3DXVECTOR3 ConvertRootTranslationAxis( const D3DXVECTOR3& translation, const MOTION_RT_AXIS& axis );
/*
		D3DXQUATERNION ComputeRootRotation(	const D3DXQUATERNION& baseRotation,
											const D3DXQUATERNION& rotation,
											const MOTION_RT_AXIS& axis );

		D3DXVECTOR3 ComputeRootTranslation( const D3DXMATRIX& baseTranslation,
											const D3DXVECTOR3& scaling,
											const D3DXQUATERNION& rotation,
											const D3DXVECTOR3& translation,
											const MOTION_RT_AXIS& axis );
*/
		bool Write( const wchar_t* pFilePath, Mix::Tool::Win32::File::OutputStream& output );

	public:
		const wchar_t* GetDefaultName( void ) const;

		void SetName( const wchar_t* pName );
		const wchar_t* GetName( void ) const;

		unsigned int GetCurveCount( void ) const;
		Mix::Tool::Win32::Graphics::MotionCurve* GetCurve( unsigned int index ) const;
		Mix::Tool::Win32::Graphics::MotionCurve* AddCurve( const char* pLinkNodeName );
		Mix::Tool::Win32::Graphics::MotionCurve* AddCurve( const wchar_t* pLinkNodeName );

		bool IsAssigned( void ) const;

		void SetDefault( bool state );
		bool GetDefault( void ) const;

		void SetSpeed( float speed );
		float GetSpeed( void ) const;

		void SetBlendRatio( float rate );
		float GetBlendRatio( void ) const;

		float GetLastTime( void ) const;

		void SetLoopStartTime( float time );
		void SetLoopEndTime( float time );
		float GetLoopStartTime( void ) const;
		float GetLoopEndTime( void ) const;

		unsigned int GetRootTransformFlags( void ) const;
		void SetRootTransformFlags( unsigned int flags );
		void UpdateRootTransform( void );
		Mix::Tool::Win32::Graphics::RootMotionCurve* GetRootTransformCurvePtr( void ) const;

		void SetSaveFilePath( const wchar_t* pFilePath );
		const wchar_t* GetSaveFilePath( void ) const;

		void Play( void );
		void Pause( void );
		void Stop( void );
		Mix::Tool::Win32::Graphics::MOTION_STATE GetState( void ) const;
		void SetTime( int time );
		int GetTime( void );

		void SetLoop( bool state );
		bool GetLoop( void ) const;

		void Finish( void );

//		bool Load( const wchar_t* pFilePath );
		bool Save( void );

		void Destroy( void );

	public:
		virtual Mix::Tool::Win32::Object::TYPE GetType( void ) const;

		friend class MotionController;
	};

}}}}
