/*!
 * Copyright (c) 2026 Vertex Software LLC. All rights reserved.
 */
'use strict';

var geometry_pb = require('./geometry_pb-C1IfJb14.js');
var wrappers_pb = require('./wrappers_pb-Dupo3Hcb.js');
var grpc = require('./grpc-BsWFEUrc.js');
var bundle$1 = require('./bundle-Dsc8KJRQ.js');
var bundle = require('./bundle-96sYCpzz.js');
var streamAttributes = require('./streamAttributes-ce88H9XR.js');

/**
 * The `MeasurementController` is responsible for performing measurements of
 * registered entities, and updating the model with their measurement results.
 */
class MeasurementController {
    constructor(model, client, jwtProvider, deviceId) {
        this.model = model;
        this.client = client;
        this.jwtProvider = jwtProvider;
        this.deviceId = deviceId;
        this.outcome = Promise.resolve(undefined);
        this.debugLogs = false;
    }
    /**
     * Registers an entity to measure and performs a measurement if this entity
     * has not been previously registered.
     *
     * @param entity The entity to measure.
     * @returns A promise that resolves with the results after registering this
     * entity.
     */
    addEntity(entity) {
        if (this.debugLogs) {
            const deserializedEntity = geometry_pb.model_entity_pbExports.ModelEntity.deserializeBinary(entity.modelEntity);
            this.log(`Adding ModelEntity. [entityId={${deserializedEntity.getEntityId()}}, sceneItemId={${deserializedEntity.getSceneItemId()}}]`);
        }
        return this.performMeasurement(() => this.model.addEntity(entity));
    }
    /**
     * Clears all entities and returns a promise that resolves with an empty list
     * of measurement results.
     */
    clearEntities() {
        this.log('Clearing all ModelEntities.');
        return this.performMeasurement(() => {
            this.model.clearEntities();
            this.model.clearOutcome();
            return true;
        });
    }
    /**
     * Deregisters an entity and performs a measurement if this entity was
     * removed.
     *
     * @param entity The entity to remove.
     * @returns A promise that resolves with the results after removing this
     * entity.
     */
    removeEntity(entity) {
        if (this.debugLogs) {
            const deserializedEntity = geometry_pb.model_entity_pbExports.ModelEntity.deserializeBinary(entity.modelEntity);
            this.log(`Removing ModelEntity. [entityId={${deserializedEntity.getEntityId()}}, sceneItemId={${deserializedEntity.getSceneItemId()}}]`);
        }
        return this.performMeasurement(() => this.model.removeEntity(entity));
    }
    /**
     * Registers a set of entities and performs a measurement
     *
     * @param entities The entities to measure.
     * @returns A promise that resolves with the results after registering these
     * entities.
     */
    setEntities(entities) {
        if (this.debugLogs) {
            const deserializedEntities = Array.from(entities).map((e) => geometry_pb.model_entity_pbExports.ModelEntity.deserializeBinary(e.modelEntity));
            this.log(`Setting ${deserializedEntities.length} ModelEntities. [entityIds=[${deserializedEntities.map((e) => e.getEntityId()).join(', ')}], sceneItemIds=[${deserializedEntities.map((e) => e.getSceneItemId()).join(', ')}]]`);
        }
        return this.performMeasurement(() => this.model.setEntities(entities));
    }
    setDebugLogs(debugLogs) {
        this.debugLogs = debugLogs;
    }
    performMeasurement(effect) {
        const previous = this.model.getEntities();
        const changed = effect();
        const entities = this.model.getEntities();
        if (changed) {
            this.measureAndUpdateModel(entities);
            this.highlightEntities(previous, entities);
        }
        return this.outcome;
    }
    measureAndUpdateModel(entities) {
        if (entities.length > 0) {
            this.outcome = this.measureEntities(entities).then((outcome) => {
                this.model.setOutcome(outcome);
                return this.model.getOutcome();
            });
        }
        else {
            this.outcome = Promise.resolve(undefined);
        }
    }
    async measureEntities(entities) {
        if (entities.length > 0) {
            const res = await grpc.requestUnary(async (handler) => {
                const meta = await grpc.createMetadata(this.jwtProvider, this.deviceId);
                const req = new wrappers_pb.scene_view_api_pbExports.MeasureRequest();
                req.setEntitiesList(entities.map((e) => e.toProto()));
                this.client.measure(req, meta, handler);
            });
            return geometry_pb.mapMeasureResponseOrThrow(res.toObject());
        }
        else {
            return undefined;
        }
    }
    async highlightEntities(previous, entities) {
        await grpc.requestUnary(async (handler) => {
            const meta = await grpc.createMetadata(this.jwtProvider, this.deviceId);
            const entitySet = new Set(entities);
            const newPrevious = previous.filter((e) => !entitySet.has(e));
            const clearEntities = newPrevious.map((e) => {
                const update = new wrappers_pb.scene_view_api_pbExports.ModelEntityUpdate();
                update.setModelEntity(geometry_pb.model_entity_pbExports.ModelEntity.deserializeBinary(e.modelEntity));
                update.setHighlight(new wrappers_pb.wrappers_pbExports.BoolValue().setValue(false));
                return update;
            });
            const highlightEntities = entities.map((e) => {
                const update = new wrappers_pb.scene_view_api_pbExports.ModelEntityUpdate();
                update.setModelEntity(geometry_pb.model_entity_pbExports.ModelEntity.deserializeBinary(e.modelEntity));
                update.setHighlight(new wrappers_pb.wrappers_pbExports.BoolValue().setValue(true));
                return update;
            });
            const req = new wrappers_pb.scene_view_api_pbExports.UpdateModelEntitiesRequest();
            req.setUpdatesList([...clearEntities, ...highlightEntities]);
            this.client.updateModelEntities(req, meta, handler);
        });
    }
    log(message, ...optionalParams) {
        if (this.debugLogs) {
            console.debug(message, optionalParams);
        }
    }
}

class MeasurementEntity {
    constructor(point, modelEntity) {
        this.point = point;
        this.modelEntity = modelEntity;
    }
    static fromHit(hit) {
        if (hit.hitPoint != null && hit.modelEntity != null) {
            const hitPoint = bundle.mapper.ifInvalidThrow(streamAttributes.fromPbVector3f)(hit.hitPoint);
            const modelEntity = bundle$1.vertexvis.protobuf.core.ModelEntity.encode(hit.modelEntity).finish();
            return new MeasurementEntity(hitPoint, modelEntity);
        }
        else {
            throw new Error('Cannot create MeasurementEntity from Hit. Hit is missing hit point and model entity');
        }
    }
    toProto() {
        const entity = new wrappers_pb.scene_view_api_pbExports.MeasureEntity();
        const point = new geometry_pb.geometry_pbExports.Vector3f();
        point.setX(this.point.x);
        point.setY(this.point.y);
        point.setZ(this.point.z);
        entity.setPoint(point);
        const modelEntity = geometry_pb.model_entity_pbExports.ModelEntity.deserializeBinary(this.modelEntity);
        entity.setModelEntity(modelEntity);
        return entity;
    }
}

exports.MeasurementController = MeasurementController;
exports.MeasurementEntity = MeasurementEntity;
//# sourceMappingURL=entities-C1pFrpRu.js.map

//# sourceMappingURL=entities-C1pFrpRu.js.map