import { assert } from "../../../../../../../assert.js";
import { bt_vert_kill } from "../vertex/bt_vert_kill.js";
import { bt_vertex_replace } from "../vertex/bt_vertex_replace.js";
import { bt_edge_kill } from "./bt_edge_kill.js";

/**
 * Collapses an edge by merging its two vertices into one, relocating the surviving
 * vertex to the supplied coordinate.
 *
 * All faces incident to the collapse edge are removed (they would become degenerate),
 * while faces that only share one of the endpoints are retained and re-stitched onto
 * the surviving vertex. The victim vertex is released.
 *
 * NOTE: Does not perform a weld pass, so collapses that share "link" vertices between
 * the two endpoints will produce duplicate (parallel) edges. The topology remains
 * self-consistent (disk and radial cycles are intact), but callers doing mesh
 * simplification typically want to run a cleanup pass afterward.
 *
 * @param {BinaryTopology} mesh
 * @param {number} edge_id The edge to collapse
 * @param {number[]|Float32Array} new_position New coordinate for the surviving vertex
 * @param {number} [new_position_offset] Offset into `new_position`
 * @returns {number} The surviving vertex ID
 */
export function bt_edge_collapse(
    mesh,
    edge_id,
    new_position,
    new_position_offset = 0
) {
    assert.defined(mesh, 'mesh');
    assert.notNull(mesh, 'mesh');
    assert.isNonNegativeInteger(edge_id, 'edge_id');
    assert.defined(new_position, 'new_position');

    const v_survivor = mesh.edge_read_vertex1(edge_id);
    const v_victim = mesh.edge_read_vertex2(edge_id);

    // 1. Kill adjacent faces and remove the collapse edge itself.
    bt_edge_kill(mesh, edge_id);

    // 2. Re-point every remaining edge/loop from the victim onto the survivor.
    bt_vertex_replace(mesh, v_victim, v_survivor);

    // 3. Release the now-disconnected victim vertex.
    bt_vert_kill(mesh, v_victim);

    // 4. Move the survivor to the requested position.
    mesh.vertex_write_coordinate(v_survivor, new_position, new_position_offset);

    return v_survivor;
}
