import { BufferAttribute, BufferGeometry } from "three";

/**
 *
 * @param {TopoMesh} mesh
 * @returns {THREE.BufferGeometry}
 */
export function topo_mesh_to_three_buffer_geometry(mesh) {
    const vertices_lookup = new Map();

    // build vertices array
    const vertex_count = mesh.vertices.length;
    const position_array = new Float32Array(vertex_count * 3);
    for (let i = 0; i < vertex_count; i++) {
        const vertex = mesh.vertices[i];

        const i_3 = i * 3;

        position_array[i_3] = vertex.x;
        position_array[i_3 + 1] = vertex.y;
        position_array[i_3 + 2] = vertex.z;

        vertices_lookup.set(vertex, i);
    }
    // build face array
    const mesh_faces = mesh.getFaces();
    const face_count = mesh_faces.size;

    let IndexArrayType;
    if (vertex_count <= 255) {
        IndexArrayType = Uint8Array;
    } else if (vertex_count <= 65535) {
        IndexArrayType = Uint16Array;
    } else {
        IndexArrayType = Uint32Array;
    }

    const face_array = new IndexArrayType(face_count * 3);

    let i_3 = 0;
    for (let face of mesh_faces) {

        const vA = face.vertices[0];
        const vB = face.vertices[1];
        const vC = face.vertices[2];

        const vAi = vertices_lookup.get(vA);
        const vBi = vertices_lookup.get(vB);
        const vCi = vertices_lookup.get(vC);

        face_array[i_3] = vAi;
        face_array[i_3 + 1] = vBi;
        face_array[i_3 + 2] = vCi;

        i_3 += 3;
    }

    const geometry = new BufferGeometry();

    geometry.setIndex(new BufferAttribute(face_array, 1));
    geometry.setAttribute("position", new BufferAttribute(position_array, 3, false))

    return geometry;
}
