#include "object.h"

Object::Object()// Initialize the reference here
{
	m_scaleMatrix = XMMatrixIdentity();
	m_rotateMatrix = XMMatrixIdentity();
	m_translateMatrix = XMMatrixIdentity();
	m_srMatrix = XMMatrixIdentity();
	m_worldMatrix = XMMatrixIdentity();
	m_previousPosition = XMVectorZero();
	m_velocity = XMVectorZero();
	m_acceleration = XMVectorZero();
	m_mass = NULL;
	m_isGrounded = false;
	m_id = NULL;
	m_boundingRadius = 1.0f;
}

Object::~Object()
{

}

void Object::SetScaleMatrix(XMMATRIX scaleMatrix)
{
	m_scaleMatrix = scaleMatrix;
}

void Object::SetRotateMatrix(XMMATRIX rotateMatrix)
{
	m_rotateMatrix = rotateMatrix;
}

void Object::SetTranslateMatrix(XMMATRIX translateMatrix)
{
	m_translateMatrix = translateMatrix;
}

void Object::SetSRMatrix(XMMATRIX srMatrix)
{
	m_srMatrix = srMatrix;
}

void Object::SetWorldMatrix(XMMATRIX worldMatrix)
{
	m_worldMatrix = worldMatrix;
}

XMMATRIX Object::GetScaleMatrix() const
{
	return m_scaleMatrix;
}

XMMATRIX Object::GetRotateMatrix() const
{
	return m_rotateMatrix;
}

XMMATRIX Object::GetTranslateMatrix() const
{
	return m_translateMatrix;
}

XMMATRIX Object::GetSRMatrix() const
{
	return m_srMatrix;
}

XMMATRIX Object::GetWorldMatrix() const
{
	return m_worldMatrix;
}

XMVECTOR Object::GetPosition()
{
	XMFLOAT4X4 matrix;
	XMStoreFloat4x4(&matrix, m_translateMatrix);
	return XMVectorSet(matrix._41, matrix._42, matrix._43, 0.0f);
}

XMVECTOR Object::GetRotation()
{
	XMFLOAT4X4 matrix;
	XMStoreFloat4x4(&matrix, m_rotateMatrix);
	float rotationX = atan2f(matrix._32, matrix._33);
	float rotationY = atan2f(-matrix._31, sqrtf(matrix._32 * matrix._32 + matrix._33 * matrix._33));
	float rotationZ = atan2f(matrix._21, matrix._11);
	return XMVectorSet(rotationX, rotationY, rotationZ, 0.0f);
}


XMVECTOR Object::GetScale()
{
	XMFLOAT4X4 matrix;
	XMStoreFloat4x4(&matrix, m_scaleMatrix);

	// Utiliser des vecteurs pour les lignes de la matrice
	XMVECTOR row1 = XMLoadFloat3(reinterpret_cast<XMFLOAT3*>(&matrix._11));
	XMVECTOR row2 = XMLoadFloat3(reinterpret_cast<XMFLOAT3*>(&matrix._21));
	XMVECTOR row3 = XMLoadFloat3(reinterpret_cast<XMFLOAT3*>(&matrix._31));

	// Calculer les longueurs des vecteurs
	XMVECTOR scale = XMVectorSet(
		XMVectorGetX(XMVector3Length(row1)),
		XMVectorGetX(XMVector3Length(row2)),
		XMVectorGetX(XMVector3Length(row3)),
		0.0f
	);

	return scale;
}



void Object::SetPosition(XMVECTOR position)
{
	XMFLOAT4X4 matrix;
	XMStoreFloat4x4(&matrix, m_translateMatrix);
	matrix._41 = XMVectorGetX(position);
	matrix._42 = XMVectorGetY(position);
	matrix._43 = XMVectorGetZ(position);
	m_translateMatrix = XMLoadFloat4x4(&matrix);
}

void Object::SetRotation(XMVECTOR rotation)
{
	XMFLOAT4X4 matrix;
	XMStoreFloat4x4(&matrix, m_rotateMatrix);
	XMMATRIX rotationMatrix = XMMatrixRotationRollPitchYaw(XMVectorGetX(rotation), XMVectorGetY(rotation), XMVectorGetZ(rotation));
	m_rotateMatrix = rotationMatrix;
}

void Object::SetScale(XMVECTOR scale)
{
	XMFLOAT4X4 matrix;
	XMStoreFloat4x4(&matrix, m_scaleMatrix);
	matrix._11 = XMVectorGetX(scale);
	matrix._22 = XMVectorGetY(scale);
	matrix._33 = XMVectorGetZ(scale);
	m_scaleMatrix = XMLoadFloat4x4(&matrix);
}

void Object::UpdateWorldMatrix()
{
	m_worldMatrix = m_scaleMatrix * m_rotateMatrix * m_translateMatrix;
}

void Object::UpdateSRMatrix()
{
	m_srMatrix = m_scaleMatrix * m_rotateMatrix;
}

void Object::UpdateTranslateMatrix()
{
	m_translateMatrix = XMMatrixTranslationFromVector(GetPosition());
}

void Object::UpdateRotateMatrix()
{
	m_rotateMatrix = XMMatrixRotationRollPitchYawFromVector(GetRotation());
}

void Object::UpdateScaleMatrix()
{
	m_scaleMatrix = XMMatrixScalingFromVector(GetScale());
}

void Object::Update()
{
	UpdateWorldMatrix();
	UpdateSRMatrix();
	UpdateTranslateMatrix();
	UpdateRotateMatrix();
	UpdateScaleMatrix();
}

std::string Object::GetName()
{
	return m_name;
}

void Object::SetName(std::string name)
{
	m_name = name;
}

void Object::SetVelocity(XMVECTOR velocity)
{
	m_velocity = velocity;
}

void Object::AddVelocity(float deltaTime)
{
	m_velocity += m_acceleration * deltaTime;
}

XMVECTOR Object::GetVelocity() const
{
	return m_velocity;
}

void Object::SetAcceleration(XMVECTOR acceleration)
{
	m_acceleration = acceleration;
}

XMVECTOR Object::GetAcceleration() const
{
	return m_acceleration;
}

void Object::SetMass(float mass)
{
	m_mass = mass;
}

float Object::GetMass() const
{
	return m_mass;
}

void Object::SetGrounded(bool isGrounded)
{
	m_isGrounded = isGrounded;
}

bool Object::IsGrounded() const
{
	return m_isGrounded;
}

int Object::SetId(int id)
{
	return m_id = id;
}

int Object::GetId() const
{
	return m_id;
}

bool Object::IsPhysicsEnabled() const
{
	return m_isPhysicsEnabled;
}

void Object::SetPhysicsEnabled(bool state)
{
	m_isPhysicsEnabled = state;
}

float Object::GetBoundingRadius() const
{
	return m_boundingRadius;
}

void Object::UpdatePosition(float deltaTime)
{
	XMVECTOR position = GetPosition();
	position = position + GetVelocity() * deltaTime;
	SetPosition(position);
}

void Object::SetType(ObjectType type)
{
	m_type = type;
}

std::string Object::ObjectTypeToString(ObjectType type) {
	switch (type) {
		case ObjectType::Cube: return "Cube";
		case ObjectType::Sphere: return "Sphere";
		// Ajoutez d'autres cas si nécessaire
		default: return "Unknown";
	}
}

ObjectType Object::StringToObjectType(const std::string& str) {
	if (str == "Cube") return ObjectType::Cube;
	if (str == "Sphere") return ObjectType::Sphere;
	// Add other cases as needed
	return ObjectType::Unknown;
}

std::string Object::ShaderTypeToString(ShaderType type) {
	switch (type) {
		case ShaderType::ALPHA_MAPPING: return "ALPHA_MAPPING";
		case ShaderType::CEL_SHADING: return "CEL_SHADING";
		case ShaderType::NORMAL_MAPPING: return "NORMAL_MAPPING";
		case ShaderType::SPECULAR_MAPPING: return "SPECULAR_MAPPING";
		case ShaderType::TEXTURE: return "TEXTURE";
		case ShaderType::LIGHTING: return "LIGHTING";
		case ShaderType::SUNLIGHT: return "SUNLIGHT";
		// Ajoutez d'autres cas si nécessaire
		default: return "Unknown";
	}
}

ShaderType Object::StringToShaderType(const std::string& str) {
	if (str == "ALPHA_MAPPING") return ShaderType::ALPHA_MAPPING;
	if (str == "CEL_SHADING") return ShaderType::CEL_SHADING;
	if (str == "NORMAL_MAPPING") return ShaderType::NORMAL_MAPPING;
	if (str == "SPECULAR_MAPPING") return ShaderType::SPECULAR_MAPPING;
	if (str == "TEXTURE") return ShaderType::TEXTURE;
	if (str == "LIGHTING") return ShaderType::LIGHTING;
	if (str == "SUNLIGHT") return ShaderType::SUNLIGHT;
	// Add other cases as needed
	return ShaderType::TEXTURE;
}