import * as THREE from 'three';
import * as Types from "../../../../types/world/worldTypes";
import * as CONSTANTS from "../../../../types/world/worldConstants";

import texturePath from "../../../../assets/textures/floor/concreteFloorWorn001Diff2k.jpg";
import normalPath from "../../../../assets/textures/floor/concreteFloorWorn001NorGl2k.jpg";

// Cache for materials
const materialCache = new Map<string, THREE.Material>();

export default function addFloorToScene(
    shape: THREE.Shape,
    layer: number,
    floorGroup: Types.RefGroup,
    userData: any,
) {
    const textureLoader = new THREE.TextureLoader();

    const textureScale = CONSTANTS.floorConfig.textureScale;

    const materialKey = `floorMaterial_${textureScale}`;

    let material: THREE.Material;

    if (materialCache.has(materialKey)) {
        material = materialCache.get(materialKey) as THREE.Material;
    } else {
        const floorTexture = textureLoader.load(texturePath);
        const normalMap = textureLoader.load(normalPath);

        floorTexture.wrapS = floorTexture.wrapT = THREE.RepeatWrapping;
        floorTexture.repeat.set(textureScale, textureScale);
        floorTexture.colorSpace = THREE.SRGBColorSpace;

        normalMap.wrapS = normalMap.wrapT = THREE.RepeatWrapping;
        normalMap.repeat.set(textureScale, textureScale);

        material = new THREE.MeshStandardMaterial({
            map: floorTexture,
            normalMap: normalMap,
            side: THREE.DoubleSide,
        });

        materialCache.set(materialKey, material);
    }

    const extrudeSettings = {
        depth: CONSTANTS.floorConfig.height,
        bevelEnabled: false,
    };

    const geometry = new THREE.ExtrudeGeometry(shape, extrudeSettings);
    const mesh = new THREE.Mesh(geometry, material);

    mesh.receiveShadow = true;
    mesh.position.y = (layer) * CONSTANTS.wallConfig.height;
    mesh.rotateX(Math.PI / 2);
    mesh.name = `Floor_Layer_${layer}`;

    // Store UUIDs for debugging or future processing
    mesh.userData.uuids = userData;

    floorGroup.current.add(mesh);
}
