/** @internal NOTE: Internal APIs. Subject to change. Use of these APIs in production applications is not supported. */ /** */
import '../MapExtensions';
import { T8Unit } from '@twinfinity/t8-client-model';
const GID_SENTINEL = 'useGlobalIdHere_ee5c4789-0e4a-4e6c-8beb-3e2ca239b4a8';
function inferType(value) {
    return typeof value === 'boolean' ? 'IfcBoolean' : typeof value === 'number' ? 'IfcReal' : 'IfcText';
}
export class BimPropertySetReader {
    _decodedPropertySetByHashCache = new Map();
    clear() {
        this._decodedPropertySetByHashCache.clear();
    }
    decodePropertySets(bimIfcPropertiesResponse) {
        const decodedPropertySets = [];
        for (const psetDto of bimIfcPropertiesResponse.propertySets) {
            let psetName = bimIfcPropertiesResponse.propertySetNames[psetDto.s];
            const psetType = psetName.startsWith('q.') ? 'quantities' : 'properties';
            psetName = psetName.slice(2);
            const cached = this._decodedPropertySetByHashCache.get(psetDto.h);
            if (cached !== undefined) {
                decodedPropertySets.push(cached);
                continue;
            }
            const { propertyNames, propertyValues, propertyUnits } = bimIfcPropertiesResponse;
            const pLen = psetDto.n.length;
            const accumulatedProps = {};
            const accumulatedUnits = {};
            let gidPropertyNames;
            for (let i = 0; i < pLen; ++i) {
                const pName = propertyNames[psetDto.n[i]];
                const value = propertyValues[psetDto.v[i]];
                const type = inferType(value);
                let unit;
                if (propertyUnits != null && psetDto.u != null && i < psetDto.u.length) {
                    const pUnitIdx = psetDto.u[i];
                    if (pUnitIdx >= 0 && pUnitIdx < propertyUnits.length) {
                        const pu = propertyUnits[pUnitIdx];
                        if (pu != null && pu.name && pu.type) {
                            unit = new T8Unit(pu.name, pu.type);
                        }
                    }
                }
                (accumulatedProps[pName] ??= []).push({ value, type, unit });
                if (unit !== undefined) {
                    accumulatedUnits[pName] = unit;
                }
            }
            // Unwrap singleton arrays and detect GID sentinel properties
            const properties = {};
            for (const [propName, propArray] of Object.entries(accumulatedProps)) {
                if (propArray.length === 1) {
                    if (propArray[0].value === GID_SENTINEL) {
                        gidPropertyNames ??= [];
                        gidPropertyNames.push(propName);
                    }
                    properties[propName] = propArray[0];
                }
                else {
                    properties[propName] = propArray;
                }
            }
            let decodedValue;
            if (psetType === 'quantities') {
                const quantities = {};
                for (const [propName, prop] of Object.entries(properties)) {
                    const single = Array.isArray(prop) ? prop[0] : prop;
                    quantities[propName] = { value: single.value, type: single.type, unit: single.unit };
                }
                decodedValue = { name: psetName, quantities };
            }
            else {
                decodedValue = { name: psetName, properties, sets: {} };
            }
            const decoded = {
                name: psetName,
                value: decodedValue,
                type: psetType,
                ...(gidPropertyNames ? { gidPropertyNames } : {})
            };
            this._decodedPropertySetByHashCache.set(psetDto.h, decoded);
            decodedPropertySets.push(decoded);
        }
        return decodedPropertySets;
    }
    getT8PropertySetForProduct(ifcObject, decoded) {
        if (!decoded.gidPropertyNames)
            return decoded.value;
        const base = decoded.value;
        const overrides = {};
        for (const propName of decoded.gidPropertyNames) {
            const existing = base.properties[propName];
            const baseProp = Array.isArray(existing) ? existing[0] : existing;
            overrides[propName] = { value: ifcObject.gid, type: baseProp?.type ?? 'IfcText', unit: baseProp?.unit };
        }
        return {
            name: base.name,
            properties: { ...base.properties, ...overrides },
            sets: base.sets
        };
    }
}
//# sourceMappingURL=bim-property-set-reader.js.map