/*!
 * Copyright (c) 2026 Vertex Software LLC. All rights reserved.
 */
import { StreamRequestError } from "@vertexvis/stream-api";
import { EventDispatcher } from "@vertexvis/utils";
export class VolumeIntersectionQueryController {
    constructor(model, viewer) {
        this.model = model;
        this.viewer = viewer;
        this.additionalTransforms = [];
        this.operationInFlight = false;
        this.operationAborted = false;
        this.executeStarted = new EventDispatcher();
        this.executeComplete = new EventDispatcher();
        this.executeAborted = new EventDispatcher();
        this.additionalTransforms = [
            (op) => op.items.where((q) => q.all()).deselect(),
        ];
        this.operationTransform = (builder) => builder.select();
    }
    setStartPoint(point) {
        this.previousViewerCameraControls = this.viewer.cameraControls;
        this.viewer.cameraControls = false;
        this.model.setStartPoint(point);
    }
    setEndPoint(point) {
        this.model.setEndPoint(point);
    }
    /**
     * Updates the operation that will be applied based on the volume intersection
     * query. Defaults to `(builder) => builder.select()`, which will select any
     * of the results of the query.
     */
    setOperationTransform(operationTransform) {
        this.operationTransform = operationTransform;
    }
    /**
     * Updates any additional operations that should be performed independent of
     * the volume intersection query. This can be used to perform an operation on
     * the entirety of the scene prior to the operation on the result of the
     * volume intersection query.
     * Defaults to `[(op) => op.items.where((q) => q.all()).deselect()]`, which will
     * clear any prior selection before the default selection.
     */
    setAdditionalTransforms(additionalTransforms) {
        this.additionalTransforms = additionalTransforms;
    }
    onExecuteStarted(listener) {
        return this.executeStarted.on(listener);
    }
    onExecuteComplete(listener) {
        return this.executeComplete.on(listener);
    }
    onExecuteAborted(listener) {
        return this.executeAborted.on(listener);
    }
    async execute() {
        var _a, _b, _c;
        const screenBounds = this.model.getScreenBounds();
        const type = this.model.getType();
        if (screenBounds != null && !this.operationInFlight) {
            this.model.complete();
            try {
                this.operationInFlight = true;
                this.executeStarted.emit();
                const additionalTransforms = (op) => this.additionalTransforms.map((t) => t(op)).flat();
                const operationTransforms = (op) => [
                    this.operationTransform(op.items.where((q) => q.withVolumeIntersection(screenBounds, type === 'exclusive'))),
                ].flat();
                const scene = await this.viewer.scene();
                await scene
                    .elements((op) => [
                    ...additionalTransforms(op),
                    ...operationTransforms(op),
                ])
                    .execute({
                    skipAwaitCorrelatedFrame: true,
                });
            }
            catch (e) {
                if (e instanceof StreamRequestError &&
                    ((_a = e.summary) === null || _a === void 0 ? void 0 : _a.toLocaleLowerCase().includes('operation aborted'))) {
                    this.executeAborted.emit(e);
                    this.operationAborted = true;
                }
                else {
                    console.error('Failed to perform volume intersection query', e);
                    throw e;
                }
            }
            finally {
                this.viewer.cameraControls = (_b = this.previousViewerCameraControls) !== null && _b !== void 0 ? _b : true;
                this.previousViewerCameraControls = undefined;
                this.operationInFlight = false;
                this.executeComplete.emit({
                    aborted: this.operationAborted,
                });
                this.operationAborted = false;
            }
        }
        else if (this.operationInFlight) {
            this.model.cancel();
            throw new Error(`Unable to perform volume intersection query as there is already one in-flight.`);
        }
        else {
            this.model.cancel();
            this.viewer.cameraControls = (_c = this.previousViewerCameraControls) !== null && _c !== void 0 ? _c : true;
        }
    }
}
//# sourceMappingURL=controller.js.map
