#include <pch.hpp>

#include <math/math.hpp>

#define GLM_ENABLE_EXPERIMENTAL
#include <glm/gtx/matrix_decompose.hpp>

namespace OpenEngine::Math {

    bool DecomposeTransform(const glm::mat4& transform,
            glm::vec3& out_translation, glm::vec3& out_rotation,
            glm::vec3& out_scale)
    {
        // 1. Extract Translation
        out_translation = glm::vec3(transform[3]);

        // 2. Extract Scale and handle Negative Scaling (Reflection)
        glm::vec3 vX = glm::vec3(transform[0]);
        glm::vec3 vY = glm::vec3(transform[1]);
        glm::vec3 vZ = glm::vec3(transform[2]);

        out_scale.x = glm::length(vX);
        out_scale.y = glm::length(vY);
        out_scale.z = glm::length(vZ);

        // If the determinant is negative, one axis is mirrored
        if (glm::determinant(transform) < 0) {
            out_scale.x *= -1.0f;
        }

        // 3. Extract Rotation (Orthonormalize)
        // Avoid division by zero if scale is near-zero
        glm::mat3 rotation_matrix;
        rotation_matrix[0] = (out_scale.x != 0.0f) ? vX / out_scale.x : glm::vec3(1, 0, 0);
        rotation_matrix[1] = (out_scale.y != 0.0f) ? vY / out_scale.y : glm::vec3(0, 1, 0);
        rotation_matrix[2] = (out_scale.z != 0.0f) ? vZ / out_scale.z : glm::vec3(0, 0, 1);

        out_rotation = glm::eulerAngles(glm::quat_cast(rotation_matrix));

        return true;
    }

}
