/*!
 * Copyright (c) 2026 Vertex Software LLC. All rights reserved.
 */
import { PmiAnnotationOperationsBuilder, SceneItemOperationsBuilder, } from "./scene";
/**
 * An interface that represents a query is "complete" and can be turned into an
 * expression.
 */
class TerminalQuery {
    constructor(inverted) {
        this.inverted = inverted;
    }
    build() {
        if (this.inverted) {
            return {
                type: 'not',
                query: this.queryExpressionBuilder(),
            };
        }
        else {
            return this.queryExpressionBuilder();
        }
    }
}
export class RootQuery {
    constructor(inverted = false) {
        this.inverted = inverted;
    }
    /**
     * Specifies that the operation should be performed on all items in the scene.
     *
     * @example
     * ```typescript
     * const viewer = document.querySelector('vertex-viewer');
     * const scene = await viewer.scene();
     *
     * // Deselect all items in the scene
     * await scene.elements((op) => [op.items.where((q) => q.all()).deselect()]).execute();
     * ```
     */
    all() {
        return new AllQuery();
    }
    /**
     * Specifies that the operation should be performed on all items that do not match any following queries.
     *
     * @example
     * ```typescript
     * const viewer = document.querySelector('vertex-viewer');
     * const scene = await viewer.scene();
     *
     * // Hide all items that are not selected
     * await scene.elements((op) => [op.items.where((q) => q.not().withSelected()).hide()]).execute();
     * ```
     */
    not() {
        return new NotSceneItemQuery(!this.inverted);
    }
    /**
     * Specifies that the operation should be performed on any item matching any one of the provided IDs.
     *
     * @example
     * ```typescript
     * const viewer = document.querySelector('vertex-viewer');
     * const scene = await viewer.scene();
     *
     * // Hide the item with the `item-uuid-1` ID and the `item-uuid-2` ID
     * await scene.elements((op) => [
     *   op.items.where((q) => q.withItemIds(['item-uuid-1', 'item-uuid-2'])).hide(),
     * ]).execute();
     * ```
     */
    withItemIds(ids) {
        return new BulkQuery(ids, 'item-id', this.inverted);
    }
    /**
     * Specifies that the operation should be performed on any item matching any one of the provided custom supplied IDs.
     *
     * @example
     * ```typescript
     * const viewer = document.querySelector('vertex-viewer');
     * const scene = await viewer.scene();
     *
     * // Hide the item with the `item-supplied-id-1` supplied ID
     * // and the `item-supplied-id-2` supplied ID
     * await scene.elements((op) => [
     *   op
     *     .items.where((q) => q.withItemIds(['item-supplied-id-1', 'item-supplied-id-2']))
     *     .hide(),
     * ]).execute();
     * ```
     */
    withSuppliedIds(ids) {
        return new BulkQuery(ids, 'supplied-id', this.inverted);
    }
    /**
     * Specifies that the operation should be performed on any item matching the provided ID.
     *
     * @example
     * ```typescript
     * const viewer = document.querySelector('vertex-viewer');
     * const scene = await viewer.scene();
     *
     * // Hide the item with the `item-uuid` ID
     * await scene.elements((op) => [
     *   op.items.where((q) => q.withItemId('item-uuid')).hide(),
     * ]).execute();
     * ```
     */
    withItemId(id) {
        return new SingleSceneItemQuery({ type: 'item-id', value: id }, this.inverted);
    }
    /**
     * Specifies that the operation should be performed on any item matching the provided custom supplied ID.
     *
     * @example
     * ```typescript
     * const viewer = document.querySelector('vertex-viewer');
     * const scene = await viewer.scene();
     *
     * // Hide the item with the `item-supplied-id` supplied ID
     * await scene.elements((op) => [
     *   op.items.where((q) => q.withSuppliedId('item-supplied-id')).hide(),
     * ]).execute();
     * ```
     */
    withSuppliedId(id) {
        return new SingleSceneItemQuery({ type: 'supplied-id', value: id }, this.inverted);
    }
    /**
     * Specifies that the operation should be performed on a range within the `<vertex-scene-tree>` component.
     *
     * @example
     * ```typescript
     * const viewer = document.querySelector('vertex-viewer');
     * const scene = await viewer.scene();
     *
     * // Hide all items from the 2nd row to the 5th row of the scene-tree
     * await scene.elements((op) => [
     *   op
     *     .items.where((q) =>
     *       q.withSceneTreeRange({
     *         start: 2,
     *         end: 5,
     *       })
     *     )
     *     .hide(),
     * ]).execute();
     * ```
     */
    withSceneTreeRange(range) {
        return new SceneTreeRangeQuery(range, this.inverted);
    }
    /**
     * Specifies that the operation should be performed on any item that has a metadata value matching the
     * filter provided for any of the keys specified. Can optionally be set to perform an exactMatch,
     * which will require that the filter matches the value exactly.
     *
     * @example
     * ```typescript
     * const viewer = document.querySelector('vertex-viewer');
     * const scene = await viewer.scene();
     *
     * // Hide all items where the `PART_NAME_KEY` includes a value of `PartName`
     * await scene.elements((op) => [
     *   op.items.where((q) => q.withMetadata('PartName', ['PART_NAME_KEY'])).hide(),
     * ]).execute();
     *
     * // Hide all items where the `PART_NAME_KEY` has exactly a value of `PartName`
     * await scene.elements((op) => [
     *   op.items.where((q) => q.withMetadata('PartName', ['PART_NAME_KEY'], true)).hide(),
     * ]).execute();
     * ```
     */
    withMetadata(filter, keys, exactMatch, removeHiddenItems) {
        return new MetadataQuery(filter, keys, exactMatch, this.inverted, removeHiddenItems);
    }
    /**
     * Specifies that the operation should be performed on any item that has been selected.
     *
     * @example
     * ```typescript
     * const viewer = document.querySelector('vertex-viewer');
     * const scene = await viewer.scene();
     *
     * // Hide all items that are selected
     * await scene.elements((op) => [op.items.where((q) => q.withSelected()).hide()]).execute();
     * ```
     */
    withSelected() {
        return new AllSelectedQuery(this.inverted);
    }
    /**
     * Specifies that the operation should be performed on any item that is visible.
     *
     * @example
     * ```typescript
     * const viewer = document.querySelector('vertex-viewer');
     * const scene = await viewer.scene();
     *
     * // Select all items that are visible
     * await scene.elements((op) => [op.items.where((q) => q.withVisible()).select()]).execute();
     * ```
     */
    withVisible() {
        return new AllVisibleQuery(this.inverted);
    }
    /**
     * Specifies that the operation should be performed on any item present at the provided `point` in the image.
     * This query operates on the item found at that `point` similar to using `withItemId` in combination with
     * `raycaster.hitItems`, which can be useful if the additional metadata from the `raycaster.hitItems`
     * method is not needed to eliminate a network request.
     *
     * @example
     * ```typescript
     * const viewer = document.querySelector('vertex-viewer');
     * const scene = await viewer.scene();
     *
     * // Select the item present at the [100, 100] coordinate of the image
     * await scene.elements((op) => [
     *   op.items.where((q) => q.withPoint(Point.create(100, 100))).select(),
     * ]).execute();
     * ```
     */
    withPoint(point) {
        return new PointQuery(point, this.inverted);
    }
    /**
     * Specifies that the operation should be performed on items within the specified `rectangle` boundary
     * within the Viewer. The `exclusive` flag here determines whether items that intersect with the `rectangle`,
     * but are not contained should be included in the result.
     *
     * @example
     * ```typescript
     * const viewer = document.querySelector('vertex-viewer');
     * const scene = await viewer.scene();
  
     * // Select all items within the specified 100x100 region of the image
     * // excluding any elements that are not fully contained by the region
     * await scene.elements((op) => [
     *   op
     *     .items.where((q) =>
     *       q.withVolumeIntersection(
     *         Rectangle.create(100, 100, 100, 100),
     *         true
     *       )
     *     )
     *     .hide(),
     * ]).execute();
  
     * // Select all items within the specified 100x100 region of the image
     * // including any elements that intersect with the region
     * await scene.elements((op) => [
     *   op
     *     .items.where((q) =>
     *       q.withVolumeIntersection(
     *         Rectangle.create(100, 100, 100, 100),
     *         false
     *       )
     *     )
     *     .hide(),
     * ]).execute();
     * ```
     */
    withVolumeIntersection(rectangle, exclusive) {
        return new VolumeIntersectionQuery(rectangle, this.inverted, exclusive);
    }
}
export class NotSceneItemQuery extends RootQuery {
    constructor(inverted) {
        super(inverted);
    }
}
export class PmiAnnotationRootQuery {
    constructor(inverted = false) {
        this.inverted = inverted;
    }
    /**
     * Specifies that the operation should be performed on all PMI annotations in the scene.
     *
     * @example
     * ```typescript
     * const viewer = document.querySelector('vertex-viewer');
     * const scene = await viewer.scene();
     *
     * // Deselect all PMI annotations in the scene
     * await scene.elements((op) => [op.annotations.where((q) => q.all()).deselect()]).execute();
     * ```
     */
    all() {
        return new AllQuery();
    }
    /**
     * Specifies that the operation should be performed on all annotations that do not match any following queries.
     *
     * @example
     * ```typescript
     * const viewer = document.querySelector('vertex-viewer');
     * const scene = await viewer.scene();
     *
     * // Hide all PMI annotations that are not selected
     * await scene.elements((op) => [op.annotations.where((q) => q.not().withSelected()).hide()]).execute();
     * ```
     */
    not() {
        return new NotAnnotationQuery(!this.inverted);
    }
    /**
     * Specifies that the operation should be performed on any annotation matching any one of the provided IDs.
     *
     * @example
     * ```typescript
     * const viewer = document.querySelector('vertex-viewer');
     * const scene = await viewer.scene();
     *
     * // Hide the annotation with the `item-uuid-1` ID and the `item-uuid-2` ID
     * await scene.elements((op) => [
     *   op.annotations.where((q) => q.withAnnotationIds(['item-uuid-1', 'item-uuid-2'])).hide(),
     * ]).execute();
     * ```
     */
    withAnnotationIds(ids) {
        return new BulkQuery(ids, 'annotation-id', this.inverted);
    }
    /**
     * Specifies that the operation should be performed on any annotation matching the provided ID.
     *
     * @example
     * ```typescript
     * const viewer = document.querySelector('vertex-viewer');
     * const scene = await viewer.scene();
     *
     * // Hide the item with the `item-uuid` ID
     * await scene.elements((op) => [
     *   op.annotations.where((q) => q.withAnnotationId('item-uuid')).hide(),
     * ]).execute();
     * ```
     */
    withAnnotationId(id) {
        return new SingleAnnotationQuery({ type: 'annotation-id', value: id }, this.inverted);
    }
}
export class NotAnnotationQuery extends PmiAnnotationRootQuery {
    constructor(inverted) {
        super(inverted);
    }
}
export class AllQuery extends TerminalQuery {
    constructor(inverted = false) {
        super(inverted);
    }
    queryExpressionBuilder() {
        return { type: 'all' };
    }
}
export class SceneTreeRangeQuery extends TerminalQuery {
    constructor(range, inverted) {
        super(inverted);
        this.range = range;
    }
    queryExpressionBuilder() {
        return {
            type: 'scene-tree-range',
            range: this.range,
        };
    }
}
export class MetadataQuery extends TerminalQuery {
    constructor(filter, keys, exactMatch, inverted, removeHiddenItems) {
        super(inverted);
        this.filter = filter;
        this.keys = keys;
        this.exactMatch = exactMatch;
        this.removeHiddenItems = removeHiddenItems;
    }
    queryExpressionBuilder() {
        return {
            type: 'metadata',
            filter: this.filter,
            keys: this.keys,
            exactMatch: this.exactMatch,
            removeHiddenItems: this.removeHiddenItems,
        };
    }
}
export class AllSelectedQuery extends TerminalQuery {
    constructor(inverted) {
        super(inverted);
    }
    queryExpressionBuilder() {
        return {
            type: 'all-selected',
        };
    }
}
export class AllVisibleQuery extends TerminalQuery {
    constructor(inverted) {
        super(inverted);
    }
    queryExpressionBuilder() {
        return {
            type: 'all-visible',
        };
    }
}
export class PointQuery extends TerminalQuery {
    constructor(point, inverted) {
        super(inverted);
        this.point = point;
    }
    queryExpressionBuilder() {
        return {
            type: 'point',
            point: this.point,
        };
    }
}
export class VolumeIntersectionQuery extends TerminalQuery {
    constructor(rectangle, inverted, exclusive) {
        super(inverted);
        this.rectangle = rectangle;
        this.exclusive = exclusive;
    }
    queryExpressionBuilder() {
        return {
            type: 'volume-intersection',
            rectangle: this.rectangle,
            exclusive: !!this.exclusive,
        };
    }
}
export class BulkQuery extends TerminalQuery {
    constructor(ids, type, inverted) {
        super(inverted);
        this.ids = ids;
        this.type = type;
    }
    queryExpressionBuilder() {
        return {
            type: 'or',
            expressions: this.ids.map((id) => {
                return {
                    type: this.type,
                    value: id,
                };
            }),
        };
    }
}
class SingleSceneItemQuery extends TerminalQuery {
    constructor(query, inverted) {
        super(inverted);
        this.query = query;
    }
    queryExpressionBuilder() {
        return { ...this.query };
    }
    and() {
        return new AndSceneItemQuery([this.query], this.inverted);
    }
    or() {
        return new OrSceneItemQuery([this.query], this.inverted);
    }
}
export class OrSceneItemQuery extends TerminalQuery {
    constructor(expressions, inverted) {
        super(inverted);
        this.expressions = expressions;
    }
    queryExpressionBuilder() {
        return { type: 'or', expressions: [...this.expressions] };
    }
    withItemId(id) {
        return new OrSceneItemQuery([...this.expressions, { type: 'item-id', value: id }], this.inverted);
    }
    withSuppliedId(id) {
        return new OrSceneItemQuery([...this.expressions, { type: 'supplied-id', value: id }], this.inverted);
    }
    or() {
        return this;
    }
}
export class AndSceneItemQuery extends TerminalQuery {
    constructor(expressions, inverted) {
        super(inverted);
        this.expressions = expressions;
    }
    queryExpressionBuilder() {
        return { type: 'and', expressions: [...this.expressions] };
    }
    withItemId(id) {
        return new AndSceneItemQuery([...this.expressions, { type: 'item-id', value: id }], this.inverted);
    }
    withSuppliedId(id) {
        return new AndSceneItemQuery([...this.expressions, { type: 'supplied-id', value: id }], this.inverted);
    }
    and() {
        return this;
    }
}
class SingleAnnotationQuery extends TerminalQuery {
    constructor(query, inverted) {
        super(inverted);
        this.query = query;
    }
    queryExpressionBuilder() {
        return { ...this.query };
    }
    and() {
        return new AndAnnotationQuery([this.query], this.inverted);
    }
    or() {
        return new OrAnnotationQuery([this.query], this.inverted);
    }
}
export class OrAnnotationQuery extends TerminalQuery {
    constructor(expressions, inverted) {
        super(inverted);
        this.expressions = expressions;
    }
    queryExpressionBuilder() {
        return { type: 'or', expressions: [...this.expressions] };
    }
    withAnnotationId(id) {
        return new OrAnnotationQuery([...this.expressions, { type: 'annotation-id', value: id }], this.inverted);
    }
    or() {
        return this;
    }
}
export class AndAnnotationQuery extends TerminalQuery {
    constructor(expressions, inverted) {
        super(inverted);
        this.expressions = expressions;
    }
    queryExpressionBuilder() {
        return { type: 'and', expressions: [...this.expressions] };
    }
    withAnnotationId(id) {
        return new AndAnnotationQuery([...this.expressions, { type: 'annotation-id', value: id }], this.inverted);
    }
    and() {
        return this;
    }
}
export class SceneElementQueryExecutor {
    get items() {
        return new SceneItemQueryExecutor();
    }
    get annotations() {
        return new PmiAnnotationsQueryExecutor();
    }
}
export class PmiAnnotationsQueryExecutor {
    where(query) {
        const expression = query(new PmiAnnotationRootQuery()).build();
        return new PmiAnnotationOperationsBuilder(expression);
    }
}
export class SceneItemQueryExecutor {
    where(query) {
        const expression = query(new RootQuery()).build();
        return new SceneItemOperationsBuilder(expression);
    }
}
//# sourceMappingURL=queries.js.map
