/*!
 * Copyright (c) 2026 Vertex Software LLC. All rights reserved.
 */
import { Point } from "@vertexvis/geometry";
export class TapInteractionHandler {
    constructor(downEvent, upEvent, moveEvent, getConfig) {
        this.downEvent = downEvent;
        this.upEvent = upEvent;
        this.moveEvent = moveEvent;
        this.getConfig = getConfig;
        this.handleDown = this.handleDown.bind(this);
        this.handleUp = this.handleUp.bind(this);
        this.handleMove = this.handleMove.bind(this);
        this.handleTouchStart = this.handleTouchStart.bind(this);
        this.handleTouchMove = this.handleTouchMove.bind(this);
        this.handleTouchEnd = this.handleTouchEnd.bind(this);
        this.handlePointerMove = this.handlePointerMove.bind(this);
        this.handlePointerEnd = this.handlePointerEnd.bind(this);
        this.clearPositions = this.clearPositions.bind(this);
        this.restartDoubleTapTimer = this.restartDoubleTapTimer.bind(this);
        this.clearDoubleTapTimer = this.clearDoubleTapTimer.bind(this);
        this.restartLongPressTimer = this.restartLongPressTimer.bind(this);
        this.clearLongPressTimer = this.clearLongPressTimer.bind(this);
        this.setPointerPositions = this.setPointerPositions.bind(this);
        this.emit = this.emit.bind(this);
    }
    dispose() {
        var _a, _b;
        (_a = this.element) === null || _a === void 0 ? void 0 : _a.removeEventListener(this.downEvent, this.handleDown);
        (_b = this.element) === null || _b === void 0 ? void 0 : _b.removeEventListener('touchstart', this.handleTouchStart);
        this.element = undefined;
        this.clearDoubleTapTimer();
        this.clearLongPressTimer();
    }
    initialize(element, api) {
        this.element = element;
        this.interactionApi = api;
        element.addEventListener(this.downEvent, this.handleDown);
        element.addEventListener('touchstart', this.handleTouchStart, {
            passive: true,
        });
    }
    handleTouchStart(event) {
        if (event.touches.length === 1) {
            this.setPointerPositions(Point.create(event.touches[0].clientX, event.touches[0].clientY));
            this.restartLongPressTimer();
            window.addEventListener('touchend', this.handleTouchEnd);
            window.addEventListener('touchmove', this.handleTouchMove);
        }
    }
    handleTouchMove(event) {
        if (event.touches.length > 0) {
            this.handlePointerMove(Point.create(event.touches[0].clientX, event.touches[0].clientY), true);
        }
    }
    handleTouchEnd(event) {
        if (this.pointerDownPosition != null) {
            window.removeEventListener('touchend', this.handleTouchEnd);
            window.removeEventListener('touchmove', this.handleTouchMove);
        }
        this.handlePointerEnd(this.pointerDownPosition);
    }
    handleDown(event) {
        this.setPointerPositions(Point.create(event.clientX, event.clientY));
        this.buttons = event.buttons;
        const eventKeys = {
            altKey: event.altKey,
            ctrlKey: event.ctrlKey,
            metaKey: event.metaKey,
            shiftKey: event.shiftKey,
        };
        this.restartLongPressTimer(eventKeys);
        window.addEventListener(this.upEvent, this.handleUp);
        window.addEventListener(this.moveEvent, this.handleMove);
    }
    handleMove(event) {
        this.handlePointerMove(Point.create(event.clientX, event.clientY), this.isTouch(event));
    }
    handleUp(event) {
        if (this.pointerDownPosition != null) {
            window.removeEventListener(this.upEvent, this.handleUp);
            window.removeEventListener(this.moveEvent, this.handleMove);
        }
        this.handlePointerEnd(Point.create(event.clientX, event.clientY), {
            altKey: event.altKey,
            ctrlKey: event.ctrlKey,
            metaKey: event.metaKey,
            shiftKey: event.shiftKey,
        }, this.buttons, this.isTouch(event));
        this.buttons = undefined;
    }
    handlePointerMove(position, isTouch) {
        var _a;
        // Ignore pointer end events for this associated touch start
        // since the distance from the start is large enough
        const threshold = ((_a = this.interactionApi) === null || _a === void 0 ? void 0 : _a.pixelThreshold(isTouch)) || 2;
        if (this.pointerDownPosition != null &&
            Point.distance(position, this.pointerDownPosition) >= threshold &&
            this.interactionTimer == null) {
            this.clearPositions();
        }
    }
    handlePointerEnd(position, keyDetails = {}, buttons = 0, isTouch = false) {
        var _a, _b;
        if (position != null) {
            if (this.longPressTimer != null) {
                this.emit((_a = this.interactionApi) === null || _a === void 0 ? void 0 : _a.tap)(position, keyDetails, buttons);
            }
            if (this.doubleTapTimer != null &&
                this.secondPointerDownPosition != null) {
                this.emit((_b = this.interactionApi) === null || _b === void 0 ? void 0 : _b.doubleTap)(position, keyDetails, buttons, this.secondPointerDownPosition);
                this.clearDoubleTapTimer();
            }
        }
        this.pointerDownPosition = undefined;
        this.clearLongPressTimer();
    }
    emit(emitter) {
        return (pointerUpPosition, keyDetails = {}, buttons = 0, pointerDownPosition, isTouch = false) => {
            var _a;
            const downPosition = pointerDownPosition || this.pointerDownPosition;
            const threshold = ((_a = this.interactionApi) === null || _a === void 0 ? void 0 : _a.pixelThreshold(isTouch)) || 1;
            let emittedPosition;
            if (this.interactionTimer != null) {
                emittedPosition = this.getCanvasPosition(downPosition || pointerUpPosition);
            }
            else if (downPosition != null &&
                Point.distance(downPosition, pointerUpPosition) <= threshold) {
                emittedPosition = this.getCanvasPosition(pointerUpPosition);
            }
            if (emittedPosition != null && emitter != null) {
                emitter(emittedPosition, keyDetails, buttons);
            }
        };
    }
    getCanvasPosition(point) {
        var _a;
        const canvasBounds = (_a = this.element) === null || _a === void 0 ? void 0 : _a.getBoundingClientRect();
        const canvasOffset = canvasBounds != null
            ? Point.create(canvasBounds.left, canvasBounds.top)
            : undefined;
        return canvasOffset != null
            ? Point.subtract(Point.create(point.x, point.y), canvasOffset)
            : undefined;
    }
    clearPositions() {
        this.pointerDownPosition = undefined;
        this.firstPointerDownPosition = undefined;
        this.secondPointerDownPosition = undefined;
        this.clearDoubleTapTimer();
        this.clearLongPressTimer();
        this.clearInteractionTimer();
    }
    clearDoubleTapTimer() {
        if (this.doubleTapTimer != null) {
            window.clearTimeout(this.doubleTapTimer);
        }
        this.doubleTapTimer = undefined;
        this.firstPointerDownPosition = undefined;
        this.secondPointerDownPosition = undefined;
    }
    restartDoubleTapTimer() {
        this.clearDoubleTapTimer();
        this.doubleTapTimer = window.setTimeout(() => this.clearDoubleTapTimer(), this.getConfig().events.doubleTapThreshold);
    }
    clearLongPressTimer() {
        if (this.longPressTimer != null) {
            window.clearTimeout(this.longPressTimer);
        }
        this.longPressTimer = undefined;
    }
    restartLongPressTimer(eventKeys = {}) {
        this.clearLongPressTimer();
        this.longPressTimer = window.setTimeout(() => {
            var _a;
            if (this.pointerDownPosition) {
                this.emit((_a = this.interactionApi) === null || _a === void 0 ? void 0 : _a.longPress)(this.pointerDownPosition, eventKeys, this.buttons);
            }
            this.clearLongPressTimer();
        }, this.getConfig().events.longPressThreshold);
    }
    restartInteractionTimer() {
        this.clearInteractionTimer();
        this.interactionTimer = window.setTimeout(() => {
            this.interactionTimer = undefined;
        }, this.getConfig().interactions.interactionDelay);
    }
    clearInteractionTimer() {
        if (this.interactionTimer != null) {
            window.clearTimeout(this.interactionTimer);
            this.interactionTimer = undefined;
        }
    }
    setPointerPositions(point) {
        this.pointerDownPosition = point;
        this.restartInteractionTimer();
        if (this.firstPointerDownPosition == null) {
            this.restartDoubleTapTimer();
            this.firstPointerDownPosition = point;
        }
        else {
            this.secondPointerDownPosition = point;
        }
    }
    isTouch(event) {
        return window.PointerEvent != null && event instanceof PointerEvent
            ? event.pointerType === 'touch'
            : false;
    }
}
//# sourceMappingURL=tapInteractionHandler.js.map
