import { meshopt_optimizeVertexCache } from "../../geometry/optimization/VertexCacheOptimizer.js";

/**
 *
 * @param {THREE.BufferGeometry} geo
 * @returns {THREE.BufferGeometry}
 */
function optimize_buffer_geometry(geo) {

    const clone = geo.clone();

    const result_index_attribute = clone.getIndex();
    const source_index_attribute = geo.getIndex();

    meshopt_optimizeVertexCache(
        result_index_attribute.array, source_index_attribute.array,
        source_index_attribute.count, geo.getAttribute("position").count
    );

    return clone;

}

/**
 *
 * @param {THREE.Object3D} gltf_scene
 * @param {PathTracedScene} scene
 */
export function three_object_to_path_traced_scene(gltf_scene, scene) {
    const optimized_geometry = new Map();


    /**
     *
     * @param {THREE.BufferGeometry} geo
     * @returns {THREE.BufferGeometry}
     */
    function process_geometry(geo) {
        const existing = optimized_geometry.get(geo);
        if (existing !== undefined) {
            return existing;
        }

        let result;

        try {
            result = optimize_buffer_geometry(geo);
        } catch (e) {
            // failed to optimize, use original
            result = geo;
        }

        optimized_geometry.set(geo, result);

        return result;
    }

    gltf_scene.updateMatrixWorld();

    gltf_scene.traverse((m) => {
        if (m.isMesh) {
            scene.createMesh(
                process_geometry(m.geometry),
                m.material,
                m.matrixWorld.elements
            );
        }
    });
}