/*!
 * Copyright (c) 2026 Vertex Software LLC. All rights reserved.
 */
import { E as EventDispatcher } from './bundle-DLfw87TV.js';

class KeyBinding {
    constructor(...bindings) {
        this.bindings = bindings.map((binding) => binding.toLowerCase());
    }
    matches(keys) {
        return (this.bindings.length > 0 &&
            this.bindings.every((binding) => this.bindingMatches(keys, binding)));
    }
    bindingMatches(keys, binding) {
        const negated = binding.includes('!');
        const key = binding.replace('!', '');
        return negated ? !keys[key] : keys[key];
    }
}

class WalkModeController {
    constructor(model) {
        this.model = model;
        this.excludeTagNames = [
            'VERTEX-SCENE-TREE',
            'VERTEX-SCENE-TREE-SEARCH',
            'VERTEX-VIEWER-PIN-TOOL',
            'INPUT',
            'TEXTAREA',
        ];
        this.excludePredicates = [];
        this.updateModelExclusions();
    }
    /**
     * @internal
     */
    updateModel(model) {
        this.model = model;
    }
    /**
     * Sets whether downstream walk mode interaction handlers are enabled.
     * Setting this value to `false` will remove all event listeners for
     * the interactions, and setting this value to `true` will add or
     * re-add the event listeners.
     */
    setEnabled(enabled) {
        this.model.setEnabled(enabled);
    }
    /**
     * Sets the `ViewerTeleportMode` to be used with a `<vertex-viewer-teleport-tool>`.
     */
    setTeleportMode(mode) {
        this.model.setTeleportMode(mode);
    }
    /**
     * Updates the configuration for downstream walk mode interaction handlers.
     *
     * `teleportHeightPercentage` - percentage used for fine-tuning the distance to offset
     * the camera from a surface when performing a `teleport-and-align`. This percentage is
     * used alongside the shortest side of the visible bounding box to determine how far to
     * place the camera from the surface that has been hit, with a larger percentage placing
     * the camera further from the surface and vice-versa. Defaults to 11.75%.
     *
     * `teleportDistancePercentage` - percentage used for fine-tuning the distance moved per
     * click with the `teleport-toward` mode. This percentage is used alongside the longest
     * side of the visible bounding box to determine how far to move the camera's position
     * with each click, with a larger percentage moving the camera further and vice-versa.
     * Defaults to 2%.
     *
     * `teleportCollisionDistance` - distance used alongside the `teleportCollisionPercentage`
     * to determine whether a click with the `teleport-toward` mode would cause a "collision",
     * or would pass through the point clicked. If such a collision would occur, the camera is
     * instead placed this distance back from the point clicked once, then allowed to pass
     * through the point on subsequent clicks. Note that this will not apply if clicks occur
     * in quick succession without setting the `depthBuffers` property on the `<vertex-viewer>`
     * to `all` frames. Defaults to `1000`.
     *
     * `keyboardWalkSpeed` - speed to move the camera when performing keyboard-based
     * walk interactions. A larger number here will result in a faster walk speed through
     * the model and vice-versa. Defaults to `5`.
     *
     * `keyboardPivotDegrees` - number of degrees to move the camera when performing
     * keyboard-based pivot interactions. Defaults to `1`.
     *
     * `keyboardRepeatIntervalMs` - number of milliseconds to repeat keyboard-based interactions.
     * this value is multiplicative with the `keyboardWalkSpeed` and `keyboardPivotDegrees`, and
     * lower numbers will result in faster movement and vice-versa. Defaults to `25`.
     *
     */
    updateConfiguration(configuration) {
        const existing = this.model.getConfiguration();
        this.model.setConfiguration({
            ...existing,
            ...configuration,
        });
    }
    /**
     * Adds a custom keybinding for a specific walk operation. This will append to the
     * existing set of keybindings to allow for multiple keybindings for a specific
     * operation. To replace the defaults, see `replaceKeyBinding`.
     */
    addKeyBinding(operation, ...keys) {
        this.model.addKeyBinding(operation, new KeyBinding(...keys));
    }
    /**
     * Adds a custom keybinding for a specific walk operation. This will replace any
     * existing keybindings to allow for overriding the default behavior.
     *
     * @example
     * ```
     * const walkModeTool = document.querySelector('vertex-viewer-walk-mode-tool');
     *
     * // Remove keybinding for the `PIVOT_UP` operation
     * walkModeTool.controller.replaceKeyBinding('PIVOT_UP');
     *
     * // Replace keybinding for `WALK_FORWARD` with `ArrowUp` instead of `w`
     * walkModeTool.controller.replaceKeyBinding('WALK_FORWARD', 'ArrowUp');
     * ```
     */
    replaceKeyBinding(operation, ...keys) {
        this.model.replaceKeyBinding(operation, new KeyBinding(...keys));
    }
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    excludeElement(...args) {
        if (typeof args[0] === 'string') {
            this.excludeTagNames = [...this.excludeTagNames, args[0]];
            this.updateModelExclusions();
            return {
                dispose: () => {
                    this.excludeTagNames = this.excludeTagNames.filter((tn) => tn !== args[0]);
                },
            };
        }
        else {
            this.excludePredicates = [...this.excludePredicates, args[0]];
            this.updateModelExclusions();
            return {
                dispose: () => {
                    this.excludePredicates = this.excludePredicates.filter((tn) => tn !== args[0]);
                },
            };
        }
    }
    updateModelExclusions() {
        this.model.setExcludedPredicate((el) => this.excludeTagNames.some((tn) => tn === el.tagName) ||
            this.excludePredicates.some((p) => p(el)));
    }
}

var ViewerWalkModeOperation;
(function (ViewerWalkModeOperation) {
    ViewerWalkModeOperation["MOVE_DOWN"] = "MOVE_DOWN";
    ViewerWalkModeOperation["MOVE_UP"] = "MOVE_UP";
    ViewerWalkModeOperation["PIVOT_DOWN"] = "PIVOT_DOWN";
    ViewerWalkModeOperation["PIVOT_LEFT"] = "PIVOT_LEFT";
    ViewerWalkModeOperation["PIVOT_RIGHT"] = "PIVOT_RIGHT";
    ViewerWalkModeOperation["PIVOT_UP"] = "PIVOT_UP";
    ViewerWalkModeOperation["WALK_BACKWARD"] = "WALK_BACKWARD";
    ViewerWalkModeOperation["WALK_FORWARD"] = "WALK_FORWARD";
    ViewerWalkModeOperation["WALK_LEFT"] = "WALK_LEFT";
    ViewerWalkModeOperation["WALK_RIGHT"] = "WALK_RIGHT";
})(ViewerWalkModeOperation || (ViewerWalkModeOperation = {}));
class WalkModeModel {
    constructor() {
        this.keyBindings = {
            [ViewerWalkModeOperation.MOVE_DOWN]: [
                new KeyBinding('PageDown', '!Shift', '!Alt'),
            ],
            [ViewerWalkModeOperation.MOVE_UP]: [
                new KeyBinding('PageUp', '!Shift', '!Alt'),
            ],
            [ViewerWalkModeOperation.PIVOT_DOWN]: [
                new KeyBinding('ArrowDown', '!Shift', '!Alt'),
            ],
            [ViewerWalkModeOperation.PIVOT_LEFT]: [
                new KeyBinding('ArrowLeft', '!Shift', '!Alt'),
            ],
            [ViewerWalkModeOperation.PIVOT_RIGHT]: [
                new KeyBinding('ArrowRight', '!Shift', '!Alt'),
            ],
            [ViewerWalkModeOperation.PIVOT_UP]: [
                new KeyBinding('ArrowUp', '!Shift', '!Alt'),
            ],
            [ViewerWalkModeOperation.WALK_BACKWARD]: [new KeyBinding('s')],
            [ViewerWalkModeOperation.WALK_FORWARD]: [new KeyBinding('w')],
            [ViewerWalkModeOperation.WALK_LEFT]: [new KeyBinding('a')],
            [ViewerWalkModeOperation.WALK_RIGHT]: [new KeyBinding('d')],
        };
        this.configuration = {
            teleportHeightPercentage: 11.75,
            teleportDistancePercentage: 2,
            teleportCollisionDistance: 1000,
            keyboardWalkSpeed: 5,
            keyboardPivotDegrees: 1,
            keyboardRepeatIntervalMs: 25,
        };
        this.enabled = true;
        this.enabledChanged = new EventDispatcher();
        this.teleportModeChanged = new EventDispatcher();
        this.configurationChanged = new EventDispatcher();
        this.keyBindingsChanged = new EventDispatcher();
    }
    setEnabled(enabled) {
        this.enabled = enabled;
        this.enabledChanged.emit(enabled);
    }
    setTeleportMode(mode) {
        this.teleportMode = mode;
        this.teleportModeChanged.emit(mode);
    }
    setConfiguration(configuration) {
        this.configuration = configuration;
        this.configurationChanged.emit(configuration);
    }
    addKeyBinding(operation, keyBinding) {
        this.keyBindings[operation] = [...this.keyBindings[operation], keyBinding];
        this.keyBindingsChanged.emit(this.keyBindings);
    }
    replaceKeyBinding(operation, keyBinding) {
        this.keyBindings[operation] = [keyBinding];
        this.keyBindingsChanged.emit(this.keyBindings);
    }
    setExcludedPredicate(predicate) {
        this.excludedPredicate = predicate;
    }
    getEnabled() {
        return this.enabled;
    }
    getTeleportMode() {
        return this.teleportMode;
    }
    getTeleportHeightPercentage() {
        return this.configuration.teleportHeightPercentage;
    }
    getKeyboardWalkSpeed() {
        return this.configuration.keyboardWalkSpeed;
    }
    getKeyboardPivotDegrees() {
        return this.configuration.keyboardPivotDegrees;
    }
    getKeyboardRepeatInterval() {
        return this.configuration.keyboardRepeatIntervalMs;
    }
    getConfiguration() {
        return this.configuration;
    }
    getKeyBindings() {
        return this.keyBindings;
    }
    operationMatches(operation, state) {
        return this.keyBindings[operation].some((binding) => binding.matches(state));
    }
    isElementExcluded(el) {
        var _a;
        return !!((_a = this.excludedPredicate) === null || _a === void 0 ? void 0 : _a.call(this, el));
    }
    onEnabledChange(listener) {
        return this.enabledChanged.on(listener);
    }
    onTeleportModeChange(listener) {
        return this.teleportModeChanged.on(listener);
    }
    onConfigurationChange(listener) {
        return this.configurationChanged.on(listener);
    }
    onKeyBindingsChange(listener) {
        return this.keyBindingsChanged.on(listener);
    }
}

export { ViewerWalkModeOperation as V, WalkModeModel as W, WalkModeController as a };
//# sourceMappingURL=model-Dru_A3Gf.js.map

//# sourceMappingURL=model-Dru_A3Gf.js.map