import { m4_invert } from "../3d/mat4/m4_invert.js";
import { v3_length } from "./v3_length.js";

const m4_inv = new Float32Array(16);

/**
 *
 * Perform rotation on a normal vector using a 4x4 affine transform matrix.
 * Input is expected to be normalized.
 * Correctly handles non-uniform scaling.
 * Output is normalized.
 *
 * @param {number[]|Float32Array} output
 * @param {number} output_offset
 * @param {number} x
 * @param {number} y
 * @param {number} z
 * @param {number[]|Float32Array} m4
 */
export function v3_matrix4_rotate_normal(
    output, output_offset,
    x, y, z,
    m4
) {

    m4_invert(m4_inv, m4);

    // this is transposed multiplication: T(M) * vec3
    const _x = m4_inv[0] * x + m4_inv[1] * y + m4_inv[2] * z;
    const _y = m4_inv[4] * x + m4_inv[5] * y + m4_inv[6] * z;
    const _z = m4_inv[8] * x + m4_inv[9] * y + m4_inv[10] * z;

    // perform normalization
    const length = v3_length(_x, _y, _z);

    if (length > 1e-7) {

        // re-normalize
        const norm = 1 / length;

        output[output_offset] = _x * norm;
        output[output_offset + 1] = _y * norm;
        output[output_offset + 2] = _z * norm;

    } else {

        // The transform is invalid.
        // Provide arbitrary vector.

        output[output_offset] = 0;
        output[output_offset + 1] = 0;
        output[output_offset + 2] = 0;

    }
}