import { compute_triangle_area_3d } from "../triangle/compute_triangle_area_3d.js";
import { tetrahedron_compute_circumsphere } from "./tetrahedron_compute_circumsphere.js";
import { tetrahedron_compute_signed_volume } from "./tetrahedron_compute_signed_volume.js";

const circ_scratch = new Float64Array(4);

/**
 * Compute the radius-ratio shape quality of a tetrahedron given by 4 vertex
 * indices into the points array. Normalised so a regular tet returns 1 and
 * a degenerate (zero-volume) tet returns 0.
 *
 * Formula: 3 · r_in / r_circ where
 *   r_in  = inscribed-sphere radius = 3·|V| / S_total
 *   r_circ = circumscribed-sphere radius
 *   S_total = sum of the 4 face areas
 *   |V| = absolute signed volume
 *
 * Quality bands (rough rule of thumb for the radius-ratio metric):
 *   1.0       regular tet
 *   ≥ 0.5     well-shaped, safe for FEM / fluid
 *   0.1–0.5   acceptable, may slow convergence
 *   0.01–0.1  sliver — usually a target for flipping / smoothing
 *   < 0.01    near-degenerate, almost flat
 *
 * Indexed form (not mesh-bound) so callers can score hypothetical tets
 * during a flip-candidate search without committing the flip first. The
 * existing mesh-form wrapper {@link compute_tetrahedron_quality} fetches
 * the four vertex IDs and forwards here.
 *
 * @param {ArrayLike<number>} points flat (x,y,z) positions
 * @param {number} a vertex index
 * @param {number} b vertex index
 * @param {number} c vertex index
 * @param {number} d vertex index
 * @returns {number} quality in [0, 1]
 */
export function tetrahedron_compute_quality(points, a, b, c, d) {
    const ax = points[a * 3],     ay = points[a * 3 + 1], az = points[a * 3 + 2];
    const bx = points[b * 3],     by = points[b * 3 + 1], bz = points[b * 3 + 2];
    const cx = points[c * 3],     cy = points[c * 3 + 1], cz = points[c * 3 + 2];
    const dx = points[d * 3],     dy = points[d * 3 + 1], dz = points[d * 3 + 2];

    // Negative signed volume → inverted tet. Treated as 0 quality so any
    // mesh-improvement driver naturally rejects moves that would produce
    // them. (For the radius-ratio shape value of the underlying triangle
    // configuration, the caller would need to take abs(vol) explicitly.)
    const signed_vol = tetrahedron_compute_signed_volume(points, a, b, c, d);
    if (signed_vol <= 0) return 0;
    const vol = signed_vol;

    const area =
        compute_triangle_area_3d(bx, by, bz, cx, cy, cz, dx, dy, dz) +
        compute_triangle_area_3d(ax, ay, az, cx, cy, cz, dx, dy, dz) +
        compute_triangle_area_3d(ax, ay, az, bx, by, bz, dx, dy, dz) +
        compute_triangle_area_3d(ax, ay, az, bx, by, bz, cx, cy, cz);

    if (area === 0) return 0;

    tetrahedron_compute_circumsphere(circ_scratch, points, a, b, c, d);
    const r_circ_sq = circ_scratch[3];
    if (!isFinite(r_circ_sq) || r_circ_sq <= 0) return 0;
    const r_circ = Math.sqrt(r_circ_sq);

    const r_in = 3 * vol / area;
    return 3 * r_in / r_circ;
}
