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

var bundle = require('./bundle-96sYCpzz.js');
var bundle$1 = require('./bundle-BhTmftd-.js');
var dom = require('./dom-CXWXs9Hx.js');

const DEFAULT_FONT_SIZE = 16;
const DEFAULT_LINE_HEIGHT = 1.2;
class BaseInteractionHandler {
    constructor(downEvent, upEvent, moveEvent, rotateInteraction, rotatePointInteraction, zoomInteraction, panInteraction, twistInteraction, pivotInteraction, getConfig) {
        this.downEvent = downEvent;
        this.upEvent = upEvent;
        this.moveEvent = moveEvent;
        this.rotateInteraction = rotateInteraction;
        this.rotatePointInteraction = rotatePointInteraction;
        this.zoomInteraction = zoomInteraction;
        this.panInteraction = panInteraction;
        this.twistInteraction = twistInteraction;
        this.pivotInteraction = pivotInteraction;
        this.getConfig = getConfig;
        this.isDragging = false;
        this.keyboardControls = false;
        this.disableIndividualInteractions = false;
        this.primaryInteractionTypeChange = new bundle.EventDispatcher();
        this.primaryInteraction = rotateInteraction;
        this.handleDownEvent = this.handleDownEvent.bind(this);
        this.handleMouseWheel = this.handleMouseWheel.bind(this);
        this.handleWindowMove = this.handleWindowMove.bind(this);
        this.handleWindowUp = this.handleWindowUp.bind(this);
        this.handleDoubleClick = this.handleDoubleClick.bind(this);
    }
    initialize(element, api) {
        this.element = element;
        this.interactionApi = api;
        element.addEventListener(this.downEvent, this.handleDownEvent);
        element.addEventListener('mousedown', this.handleDoubleClick);
        element.addEventListener('wheel', this.handleMouseWheel, {
            passive: false,
        });
    }
    dispose() {
        var _a, _b, _c;
        (_a = this.element) === null || _a === void 0 ? void 0 : _a.removeEventListener(this.downEvent, this.handleDownEvent);
        (_b = this.element) === null || _b === void 0 ? void 0 : _b.removeEventListener('mousedown', this.handleDoubleClick);
        (_c = this.element) === null || _c === void 0 ? void 0 : _c.removeEventListener('wheel', this.handleMouseWheel);
        this.element = undefined;
    }
    onPrimaryInteractionTypeChange(listener) {
        return this.primaryInteractionTypeChange.on(listener);
    }
    setCurrentInteractionType(type) {
        var _a;
        switch (type) {
            case 'rotate':
                this.currentInteraction = this.rotateInteraction;
                break;
            case 'zoom':
                this.currentInteraction = this.zoomInteraction;
                break;
            case 'pan':
                this.currentInteraction = this.panInteraction;
                break;
            case 'twist':
                this.currentInteraction = this.twistInteraction;
                break;
            case 'rotate-point':
                this.currentInteraction = this.rotatePointInteraction;
                break;
            case 'pivot':
                this.currentInteraction = this.pivotInteraction;
                break;
            default:
                this.currentInteraction = undefined;
        }
        if (this.draggingInteraction) {
            const point = this.draggingInteraction.getPosition();
            this.draggingInteraction =
                this.currentInteraction || this.primaryInteraction;
            (_a = this.interactionApi) === null || _a === void 0 ? void 0 : _a.resetLastAngle();
            this.draggingInteraction.setPosition(point);
        }
    }
    getPrimaryInteractionType() {
        return this.primaryInteraction.getType();
    }
    getCurrentInteractionType() {
        return (this.currentInteraction || this.primaryInteraction).getType();
    }
    setPrimaryInteractionType(type) {
        switch (type) {
            case 'rotate':
                this.primaryInteraction = this.rotateInteraction;
                this.lastPrimaryRotateInteraction = this.rotateInteraction;
                break;
            case 'rotate-point':
                this.primaryInteraction = this.rotatePointInteraction;
                this.lastPrimaryRotateInteraction = this.rotatePointInteraction;
                break;
            case 'zoom':
                this.primaryInteraction = this.zoomInteraction;
                break;
            case 'pan':
                this.primaryInteraction = this.panInteraction;
                break;
            case 'pivot':
                this.primaryInteraction = this.pivotInteraction;
                break;
        }
        this.primaryInteractionTypeChange.emit();
    }
    setDefaultKeyboardControls(keyboardControls) {
        this.keyboardControls = keyboardControls;
    }
    handleDownEvent(event) {
        // Prevent selection of any text while interacting with the model.
        event.preventDefault();
        this.interactionTimer = window.setTimeout(() => {
            this.downPosition = bundle$1.point.create(event.screenX, event.screenY);
            this.downPositionCanvas = this.getCanvasPosition(event);
            this.interactionTimer = undefined;
            // Perform the current movement in the case that the interaction timer elapses
            if (this.lastMoveEvent != null) {
                this.handleWindowMove(this.lastMoveEvent);
            }
        }, this.getConfig().interactions.interactionDelay);
        window.addEventListener(this.moveEvent, this.handleWindowMove);
        window.addEventListener(this.upEvent, this.handleWindowUp);
    }
    handleWindowMove(event) {
        if (this.interactionTimer == null) {
            if (this.disableIndividualInteractions) {
                return;
            }
            const position = bundle$1.point.create(event.screenX, event.screenY);
            const pixelThreshold = this.interactionApi != null
                ? this.interactionApi.pixelThreshold(this.isTouch(event))
                : 2;
            if (this.downPosition != null &&
                bundle$1.point.distance(position, this.downPosition) >= pixelThreshold &&
                !this.isDragging) {
                this.beginDrag(event);
                this.isDragging = true;
            }
            if (this.isDragging) {
                this.drag(event);
            }
        }
        this.lastMoveEvent = event;
    }
    async handleWindowUp(event) {
        if (this.isDragging) {
            this.endDrag(event);
            this.isDragging = false;
        }
        if (this.interactionTimer != null) {
            window.clearTimeout(this.interactionTimer);
            this.interactionTimer = undefined;
        }
        window.removeEventListener(this.moveEvent, this.handleWindowMove);
        window.removeEventListener(this.upEvent, this.handleWindowUp);
        this.lastMoveEvent = undefined;
    }
    async handleDoubleClick(event) {
        // event.detail is the number of clicks that have happened recently. If the number is 2, then the user double clicked.
        if (event.detail === 2 &&
            event.buttons === 4 &&
            this.interactionApi != null) {
            await this.interactionApi.viewAll();
        }
    }
    beginDrag(event) {
        var _a;
        if (this.keyboardControls && event.metaKey && event.shiftKey) {
            this.currentInteraction = this.rotatePointInteraction;
        }
        else if (this.keyboardControls && event.shiftKey && event.altKey) {
            this.currentInteraction = this.twistInteraction;
        }
        else if (this.keyboardControls && event.shiftKey) {
            this.currentInteraction = this.zoomInteraction;
        }
        else if (this.keyboardControls && (event.metaKey || event.ctrlKey)) {
            this.currentInteraction = this.panInteraction;
        }
        else if (this.keyboardControls && event.altKey) {
            this.currentInteraction = this.rotateInteraction;
        }
        if (event.buttons === 1) {
            this.draggingInteraction =
                this.currentInteraction || this.primaryInteraction;
        }
        else if (event.buttons === 2) {
            this.draggingInteraction = this.panInteraction;
        }
        else if (event.buttons === 4) {
            this.draggingInteraction =
                (_a = this.lastPrimaryRotateInteraction) !== null && _a !== void 0 ? _a : this.rotateInteraction;
        }
        if (this.draggingInteraction != null &&
            this.interactionApi != null &&
            this.element != null) {
            // Ensure any scroll wheel interactions have been ended prior to beginning
            // another interaction to prevent the interaction from being ended early.
            this.zoomInteraction.endDrag(event, this.interactionApi);
            this.draggingInteraction.beginDrag(event, this.downPositionCanvas || bundle$1.point.create(event.clientX, event.clientY), this.interactionApi, this.element);
        }
    }
    drag(event) {
        if (this.keyboardControls && event.altKey && event.shiftKey) {
            this.currentInteraction = this.twistInteraction;
        }
        else {
            this.currentInteraction = undefined;
        }
        this.draggingInteraction =
            this.currentInteraction ||
                this.draggingInteraction ||
                this.primaryInteraction;
        if (this.draggingInteraction != null && this.interactionApi != null) {
            this.draggingInteraction.drag(event, this.interactionApi);
        }
    }
    endDrag(event) {
        if (this.keyboardControls &&
            this.currentInteraction === this.twistInteraction) {
            this.currentInteraction = undefined;
        }
        if (this.draggingInteraction != null && this.interactionApi != null) {
            this.draggingInteraction.endDrag(event, this.interactionApi);
            this.draggingInteraction = undefined;
        }
    }
    async handleMouseWheel(event) {
        event.preventDefault();
        if (this.element != null &&
            this.interactionApi != null &&
            event.buttons !== 4) {
            const delta = -this.wheelDeltaToPixels(event.deltaY, event.deltaMode) / 10;
            const rect = this.element.getBoundingClientRect();
            const point = dom.getMouseClientPosition(event, rect);
            if (Math.abs(event.deltaY) < 10) {
                // For small wheel movements, send a single zoom event.
                await this.zoomInteraction.zoomToPoint(point, delta, this.interactionApi);
            }
            else {
                // For large wheel movements, divide the delta into 10 equal zoom events.
                // This results in a smoother zoom experience for the end user.
                for (let index = 1; index <= 10; index++) {
                    window.setTimeout(() => {
                        if (this.interactionApi != null) {
                            const zoomDelta = delta / 10;
                            this.zoomInteraction.zoomToPoint(point, zoomDelta, this.interactionApi);
                        }
                    }, index * 5);
                }
            }
        }
    }
    wheelDeltaToPixels(deltaY, deltaMode) {
        if (this.computedBodyStyle == null) {
            this.computedBodyStyle = window.getComputedStyle(document.body);
        }
        const defaultLineHeight = this.computedBodyStyle.getPropertyValue('fontSize') != null &&
            this.computedBodyStyle.getPropertyValue('fontSize') !== '' &&
            !isNaN(parseFloat(this.computedBodyStyle.getPropertyValue('fontSize')))
            ? parseFloat(this.computedBodyStyle.getPropertyValue('fontSize')) *
                DEFAULT_LINE_HEIGHT
            : DEFAULT_FONT_SIZE * DEFAULT_LINE_HEIGHT;
        if (deltaMode === 1) {
            // deltaMode 1 corresponds to DOM_DELTA_LINE, which computes deltas in lines
            return this.computedBodyStyle.getPropertyValue('lineHeight') != null &&
                this.computedBodyStyle.getPropertyValue('lineHeight') !== '' &&
                !isNaN(parseFloat(this.computedBodyStyle.getPropertyValue('lineHeight')))
                ? deltaY *
                    parseFloat(this.computedBodyStyle.getPropertyValue('lineHeight'))
                : deltaY * defaultLineHeight;
        }
        else if (deltaMode === 2) {
            // deltaMode 2 corresponds to DOM_DELTA_PAGE, which computes deltas in pages
            return this.computedBodyStyle.getPropertyValue('height') != null &&
                this.computedBodyStyle.getPropertyValue('height') !== '' &&
                !isNaN(parseFloat(this.computedBodyStyle.getPropertyValue('height')))
                ? deltaY * parseFloat(this.computedBodyStyle.getPropertyValue('height'))
                : deltaY * window.innerHeight;
        }
        // deltaMode 0 corresponds to DOM_DELTA_PIXEL, which computes deltas in pixels
        return deltaY;
    }
    getCanvasPosition(event) {
        var _a;
        const canvasBounds = (_a = this.element) === null || _a === void 0 ? void 0 : _a.getBoundingClientRect();
        const canvasOffset = canvasBounds != null
            ? bundle$1.point.create(canvasBounds.left, canvasBounds.top)
            : undefined;
        return canvasOffset != null
            ? bundle$1.point.subtract(bundle$1.point.create(event.clientX, event.clientY), canvasOffset)
            : undefined;
    }
    isTouch(event) {
        return window.PointerEvent != null && event instanceof PointerEvent
            ? event.pointerType === 'touch'
            : false;
    }
}

class MultiElementInteractionHandler extends BaseInteractionHandler {
    constructor() {
        super(...arguments);
        this.registeredExternalElements = {};
    }
    registerAdditionalElement(external) {
        const id = bundle.uuid.create();
        const disposable = this.addEventListenersToElement(external);
        this.registeredExternalElements[id] = disposable;
        return disposable;
    }
    deregisterAdditionalElementById(id) {
        const externalElement = this.registeredExternalElements[id];
        externalElement.dispose();
        this.registeredExternalElements = Object.fromEntries(Object.entries(this.registeredExternalElements).filter(([key]) => key !== id));
    }
    deregisterAllListeners() {
        Object.keys(this.registeredExternalElements).forEach((id) => this.deregisterAdditionalElementById(id));
    }
}

exports.BaseInteractionHandler = BaseInteractionHandler;
exports.MultiElementInteractionHandler = MultiElementInteractionHandler;
//# sourceMappingURL=multiElementInteractionHandler-CV_R_zWs.js.map

//# sourceMappingURL=multiElementInteractionHandler-CV_R_zWs.js.map