"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.cleanEntity = cleanEntity;
const entity_utils_1 = require("./entity-utils");
const TEXTURE_FIELDS = [
    'top',
    'bottom',
    'north',
    'south',
    'east',
    'west',
    'sides',
    'all',
    'topOverlay',
    'bottomOverlay',
    'northOverlay',
    'southOverlay',
    'eastOverlay',
    'westOverlay',
    'sidesOverlay',
    'allOverlay',
];
const collectGeometryPrimitives = (entity, target) => {
    const visitNode = (node) => {
        if (!node) {
            return;
        }
        if (typeof node.mesh === 'string' && node.mesh.trim().length > 0) {
            target.add(node.mesh);
        }
        (node.children ?? []).forEach(visitNode);
    };
    if (entity.geometry?.root) {
        visitNode(entity.geometry.root);
    }
};
const collectComboPrimitiveRefs = (primitive, target) => {
    primitive.slots?.forEach(slot => {
        if (slot?.primitive) {
            target.add(slot.primitive);
        }
    });
};
const collectPrimitiveResources = (primitive, textures, materials) => {
    switch (primitive.kind) {
        case 'plain_box':
            if (primitive.material) {
                materials.add(primitive.material);
            }
            break;
        case 'textured_box': {
            const box = primitive;
            TEXTURE_FIELDS.forEach(field => {
                const textureId = box[field];
                if (typeof textureId === 'string') {
                    textures.add(textureId);
                }
            });
            break;
        }
        case 'voxel_box':
            primitive.palette?.forEach(materialId => {
                if (typeof materialId === 'string') {
                    materials.add(materialId);
                }
            });
            break;
        case 'combo_box':
            break;
        default:
            break;
    }
};
const expandPrimitiveGraph = (entity, roots) => {
    const primitives = new Map(entity.primitives.map(primitive => [primitive.id, primitive]));
    const queue = Array.from(roots);
    while (queue.length > 0) {
        const id = queue.pop();
        if (!id) {
            continue;
        }
        const primitive = primitives.get(id);
        if (!primitive) {
            continue;
        }
        if (primitive.kind === 'combo_box') {
            (primitive.slots ?? []).forEach(slot => {
                if (slot?.primitive && !roots.has(slot.primitive)) {
                    roots.add(slot.primitive);
                    queue.push(slot.primitive);
                }
            });
        }
    }
    return roots;
};
function cleanEntity(entity) {
    const clone = (0, entity_utils_1.cloneEntity)(entity);
    const usedPrimitiveIds = expandPrimitiveGraph(clone, (() => {
        const ids = new Set();
        collectGeometryPrimitives(clone, ids);
        return ids;
    })());
    const usedTextureIds = new Set();
    const usedPatternIds = new Set();
    const usedMaterialIds = new Set();
    const primitiveLookup = new Map(clone.primitives.map(primitive => [primitive.id, primitive]));
    const textureLookup = new Map(clone.textures.map(texture => [texture.id, texture]));
    usedPrimitiveIds.forEach(id => {
        const primitive = primitiveLookup.get(id);
        if (!primitive) {
            return;
        }
        collectPrimitiveResources(primitive, usedTextureIds, usedMaterialIds);
    });
    usedTextureIds.forEach(textureId => {
        const texture = textureLookup.get(textureId);
        if (!texture) {
            return;
        }
        if (typeof texture.pattern === 'string') {
            usedPatternIds.add(texture.pattern);
        }
        texture.materials?.forEach(materialId => {
            if (typeof materialId === 'string') {
                usedMaterialIds.add(materialId);
            }
        });
    });
    const originalPrimitives = clone.primitives.map(primitive => primitive.id);
    const originalTextures = clone.textures.map(texture => texture.id);
    const originalPatterns = clone.patterns.map(pattern => pattern.id);
    const originalMaterials = clone.materials.map(material => material.id);
    clone.primitives = clone.primitives.filter(primitive => usedPrimitiveIds.has(primitive.id));
    clone.textures = clone.textures.filter(texture => usedTextureIds.has(texture.id));
    clone.patterns = clone.patterns.filter(pattern => usedPatternIds.has(pattern.id));
    clone.materials = clone.materials.filter(material => usedMaterialIds.has(material.id));
    return {
        entity: clone,
        removed: {
            primitives: originalPrimitives.filter(id => !usedPrimitiveIds.has(id)),
            textures: originalTextures.filter(id => !usedTextureIds.has(id)),
            patterns: originalPatterns.filter(id => !usedPatternIds.has(id)),
            materials: originalMaterials.filter(id => !usedMaterialIds.has(id)),
        },
    };
}
//# sourceMappingURL=entity-cleaner.js.map