import { v3_dot } from "../../../vec3/v3_dot.js";
import { v3_compute_triangle_normal } from "../../triangle/v3_compute_triangle_normal.js";

const scratch_normal = new Float32Array(6);

/**
 * Used to detect face normal flips for mesh optimization.
 *
 * Optimized function for computing dot product between original face normal and the normal of face that results from moving one of the vertices
 * If result is less than 0 - face normal will be flipped by this face change
 * NOTE: Idea is borrowed from blender's code, we avoid vector normalization which is quite costly as it involved SQRT operation
 * @see https://github.com/blender/blender/blob/594f47ecd2d5367ca936cf6fc6ec8168c2b360d0/source/blender/bmesh/tools/bmesh_decimate_collapse.c
 * @param {TopoTriangle} face
 * @param {TopoVertex} vertex_old
 * @param {TopoVertex} vertex_new
 * @returns {number} dot product between given face's normal and the normal of the face after altering one of the vertices
 */
export function compute_face_normal_change_dot_product(face, vertex_old, vertex_new) {
    const face_vertices = face.vertices;

    const original_v0 = face_vertices[0];
    const original_v1 = face_vertices[1];
    const original_v2 = face_vertices[2];

    let v0 = original_v0;
    let v1 = original_v1;
    let v2 = original_v2;

    if (v0 === vertex_old) {
        v0 = vertex_new;
    }

    if (v1 === vertex_old) {
        v1 = vertex_new;
    }

    if (v2 === vertex_old) {
        v2 = vertex_new;
    }

    // compute modified face normal
    v3_compute_triangle_normal(
        scratch_normal, 0,
        v0.x, v0.y, v0.z,
        v1.x, v1.y, v1.z,
        v2.x, v2.y, v2.z
    )

    // compute current face normal
    v3_compute_triangle_normal(
        scratch_normal, 3,
        original_v0.x, original_v0.y, original_v0.z,
        original_v1.x, original_v1.y, original_v1.z,
        original_v2.x, original_v2.y, original_v2.z
    )

    return v3_dot(
        scratch_normal[0], scratch_normal[1], scratch_normal[2],
        scratch_normal[3], scratch_normal[4], scratch_normal[5]
    );
}
