import { assert } from "../../../../assert.js";
import { query_edge_other_vertex } from "../query/query_edge_other_vertex.js";
import { query_face_get_other_edges } from "../query/query_face_get_other_edges.js";
import { tm_edge_kill } from "../tm_edge_kill.js";
import { tm_edge_splice } from "../tm_edge_splice.js";
import { tm_vert_splice } from "../tm_vert_splice.js";

/**
 *
 * @type {TopoEdge[]}
 */
const scratch_edges_0 = [];

/**
 *
 * @param {TopoMesh} mesh
 * @param {TopoEdge} edge
 * @param {TopoVertex} other
 * @returns {boolean}
 */
export function tm_edge_collapse(mesh, edge, other) {

    const victim = query_edge_other_vertex(edge, other);

    assert.notNull(other, 'other');
    assert.notEqual(victim, other, 'degenerate edge');

    const edge_faces = edge.faces;
    const attached_face_count = edge_faces.length;

    let recorded_splice_edge_count = 0;
    for (let i = 0; i < attached_face_count; i++) {
        const edge_face = edge_faces[i];

        const rec_address = recorded_splice_edge_count * 2;
        const got_tri_edges = query_face_get_other_edges(scratch_edges_0, rec_address, edge_face, edge);

        if (!got_tri_edges) {
            continue;
        }

        const a_v0 = scratch_edges_0[rec_address];
        const a_v1 = scratch_edges_0[rec_address + 1];

        for (let j = 0; j < rec_address; j++) {
            const other_edge = scratch_edges_0[j];

            if (other_edge === a_v0 || other_edge === a_v1) {
                // rare case, triangles share edges, avoid
                return false;
            }
        }

        recorded_splice_edge_count++;
    }

    // debugValidateMesh(mesh);

    tm_edge_kill(mesh, edge);

    tm_vert_splice(mesh, other, victim);

    for (let i = 0; i < recorded_splice_edge_count; i++) {
        const i2 = i * 2;
        tm_edge_splice(mesh, scratch_edges_0[i2], scratch_edges_0[i2 + 1]);
    }

    // debugValidateMesh(mesh);

    return true;
}
