#pragma once

//! @file Mix/Dynamics/IVehicle.h
//! @brief ビハイクルインターフェースインクルードファイル

#include "Mix/Dynamics/IObject.h"

namespace Mix{ namespace Dynamics{

	//! @class IVehicleWheel
	//! @brief ビハイクルホイールインターフェース
	class IVehicleWheel : public Mix::Reference
	{
	public:
		//! @struct TIRE
		//! @brief タイヤ構造体
		struct TIRE
		{
			Float32 radius;			//!< 半径
			Float32 friction;		//!< 摩擦係数
		};

		//! @struct SUSPENSION
		//! @brief サスペンション構造体
		struct SUSPENSION
		{
			Float32 restLength;			//!< 長さ(メートル単位)
			Float32 maxTravelCm;		//!< 稼動範囲(センチメートル単位)
			Float32 maxForce;			//!< 最大フォース
			Float32 springStiffness;	//!< バネの剛さ
			Float32 damperRelaxation;	//!< バネが伸びる際に適用されるダンパーの減衰値
			Float32 damperCompression;	//!< バネが縮む際に適用されるダンパーの減衰値
		};

		//! @struct CONTACT
		//! @brief コンタクト構造体
		struct CONTACT
		{
			Mix::Vector3 worldPosition;	//!< 接触位置のワールド座標
			Mix::Vector3 worldNormal;	//!< 接触位置のワールド法線
		};

	protected:
		//! @brief デストラクタ
		virtual ~IVehicleWheel( void ) {}

	public:
		//! @brief フロントかどうかを取得します
		//! @return フロントの場合は True を返します
		virtual Boolean IsFront( void ) const = 0;
		//! @brief 方向を取得します
		//! @return 方向を表す Mix::Vector3 クラスを返します
		virtual const Mix::Vector3& GetDirection( void ) const = 0;
		//! @brief 軸を取得します
		//! @return 軸を表す Mix::Vector3 クラスを返します
		virtual const Mix::Vector3& GetAxis( void ) const = 0;

		//! @brief 接続位置を取得します
		//! @return 接続位置を表す Mix::Vector3 クラスを返します
		virtual const Mix::Vector3& GetConnectionPoint( void ) const = 0;
		//! @brief 接続位置を設定します
		//! @param[in] cp 接続位置を表す Mix::Vector3 クラス
		virtual void SetConnectionPoint( const Mix::Vector3& cp ) = 0;

		//! @brief 車体が転がる影響度を取得します
		//! @return 影響度を返します
		virtual Float32 GetRollInfluence( void ) const = 0;
		//! @brief 車体が転がる影響度を設定します
		//! @param[in] rollInfluence 影響度
		//! @note 値が高いほど、ステアリングをきった時などに車体が転がりやすくなります
		virtual void SetRollInfluence( Float32 rollInfluence ) = 0;

		//! @brief タイヤを取得します
		//! @return タイヤを表す Mix::Dynamics::IVehicleWheel::TIRE 構造体を返します
		virtual const Mix::Dynamics::IVehicleWheel::TIRE& GetTire( void ) const = 0;
		//! @brief タイヤを設定します
		//! @param[in] tire タイヤを表す Mix::Dynamics::IVehicleWheel::TIRE 構造体
		virtual void SetTire( const Mix::Dynamics::IVehicleWheel::TIRE& tire ) = 0;

		//! @brief サスペンションを取得します
		//! @return サスペンションを表す Mix::Dynamics::IVehicleWheel::SUSPENSION 構造体を返します
		virtual const Mix::Dynamics::IVehicleWheel::SUSPENSION& GetSuspension( void ) const = 0;
		//! @brief サスペンションを設定します
		//! @param[in] suspension サスペンションを表す Mix::Dynamics::IVehicleWheel::SUSPENSION 構造体
		virtual void SetSuspension( const Mix::Dynamics::IVehicleWheel::SUSPENSION& suspension ) = 0;

		//! @brief ステアリングの値を取得します
		//! @return ステアリングの値を返します
		virtual Float32 GetSteeringValue( void ) const = 0;
		//! @brief ステアリングの値を設定します
		//! @param[in] value ステアリングの値( ラジアン単位 )
		virtual void SetSteeringValue( Float32 value ) = 0;

		//! @brief エンジンを力を取得します
		//! @return エンジンの力を返します
		virtual Float32 GetEngineForce( void ) const = 0;
		//! @brief エンジンの力を設定します
		//! @param[in] force エンジンの力
		virtual void SetEngineForce( Float32 force ) = 0;

		//! @brief ブレーキの力を取得します
		//! @return ブレーキの力を返します
		virtual Float32 GetBreakingForce( void ) const = 0;
		//! @brief ブレーキの力を設定します
		//! @param[in] force ブレーキの力
		virtual void SetBreakingForce( Float32 force ) = 0;

		//! @brief 接地しているかどうかを確認します
		//! @return 接地している場合は True を返します
		virtual Boolean OnGround( void ) const = 0;

		//! @brief 接触を取得します
		//! @return 接触を表す Mix::Dynamics::IVehicleWheel::CONTACT 構造体を返します
		//! @note 接地していない場合( OnGround() == False )、位置、法線は ( 0.0f, 0.0f, 0.0f ) が設定されます。
		virtual Mix::Dynamics::IVehicleWheel::CONTACT GetContact( void ) const = 0;

		//! @brief ワールド行列を取得します
		//! @return ワールド行列を表す Mix::Matrix4x4 クラスを返します
		virtual const Mix::Matrix4x4& GetWorldMatrix( void ) = 0;
	};

	//! @class IVehicle
	//! @brief ビハイクルインターフェース
	class IVehicle : public Mix::Dynamics::IObject
	{
	protected:
		//! @brief デストラクタ
		virtual ~IVehicle( void ) {}

	public:
		//! @brief リセットします
		//! @note ｢速度｣｢接触｣｢サスペンション｣をクリアします
		virtual void Reset( void ) = 0;
		//! @brief リセットします
		//! @param[in] worldRot リセット後の回転を表す Mix::Quaternion クラス
		//! @param[in] worldPos リセット後の位置を表す Mix::Vector3 クラス
		//! @note ｢速度｣｢接触｣｢サスペンション｣をクリアします
		virtual void Reset( const Mix::Quaternion& worldRot, const Mix::Vector3& worldPos ) = 0;

		//! @brief ホイールの数を取得します
		//! @return ホイールの数を返します
		virtual UInt32 GetWheelNum( void ) const = 0;
		//! @brief ホイールを取得します
		//! @param[in] wheelIndex ホイールのインデックス
		//! @param[out] ppWheel ホイールを表す Mix::Dynamics::IVehicleWheel インターフェースのポインタのアドレス
		//! @return 成功した場合は True を返します
		//! @note 取得したホイールは参照カウントを +1 します
		virtual Boolean GetWheel( UInt32 wheelIndex, Mix::Dynamics::IVehicleWheel** ppWheel ) = 0;
		//! @brief ホイールのポインタを取得します
		//! @param[in] wheelIndex ホイールのインデックス
		//! @return ホイールを表す Mix::Dynamics::IVehicleWheel インターフェースのポインタを返します
		virtual Mix::Dynamics::IVehicleWheel* GetWheelPtr( UInt32 wheelIndex ) const = 0;

		//! @brief 毎時の速度(キロメートル単位)を取得します
		//! @return 毎時の速度を返します
		virtual Float32 GetCurrentSpeedKmHour( void ) const = 0;
	};

}}
