using System;
using System.Numerics;
using NitroxModel.DataStructures.Unity;

namespace NitroxModel.Helper;

// ReSharper disable once InconsistentNaming
public static class Matrix4x4Extension
{
    public static Matrix4x4 Compose(NitroxVector3 localPosition, NitroxQuaternion localRotation, NitroxVector3 localScale)
    {
        Matrix4x4 translationMatrix = Matrix4x4.CreateTranslation(localPosition.X, localPosition.Y, localPosition.Z);
        Matrix4x4 rotationMatrix = Matrix4x4.CreateFromQuaternion((Quaternion)localRotation);
        Matrix4x4 scaleMatrix = Matrix4x4.CreateScale(localScale.X, localScale.Y, localScale.Z);
        return scaleMatrix * rotationMatrix * translationMatrix;
    }

    public static Matrix4x4 Invert(this Matrix4x4 m)
    {
        Matrix4x4.Invert(m, out Matrix4x4 result);
        return result;
    }

    public static NitroxVector3 Transform(this Matrix4x4 m, NitroxVector3 v)
    {
        float x = v.X * m.M11 + v.Y * m.M21 + v.Z * m.M31 + m.M41;
        float y = v.X * m.M12 + v.Y * m.M22 + v.Z * m.M32 + m.M42;
        float z = v.X * m.M13 + v.Y * m.M23 + v.Z * m.M33 + m.M43;
        float w = v.X * m.M14 + v.Y * m.M24 + v.Z * m.M34 + m.M44;

        if (w == 0)
        {
            throw new ArithmeticException($"Tried to divide by zero with Matrix {m} and vector {v}");
        }

        w = 1f / w;

        return new NitroxVector3(x * w, y * w, z * w);
    }
}
