/*!
 * Copyright (c) 2026 Vertex Software LLC. All rights reserved.
 */
import { Point } from "@vertexvis/geometry";
import { measurementWithArrowCursor } from "../cursors";
import { getMouseClientPosition } from "../dom";
import { ElementRectObserver } from "../elementRectObserver";
import { MeasurementEntity } from "./entities";
export class MeasurementInteractionHandler {
    get elementRect() {
        return this.rectObserver.rect;
    }
    constructor(controller, measurableEntityTypes) {
        this.rectObserver = new ElementRectObserver();
        this.handlePointerMove = async (event) => {
            if (await this.isMeasurableEntityUnderPointer(event)) {
                this.clearCursor();
                this.addCursor(measurementWithArrowCursor);
            }
            else {
                this.clearCursor();
            }
        };
        this.handlePointerDown = (event) => {
            this.ifNoInteraction(event, async () => {
                if (await this.isMeasurableEntityUnderPointer(event)) {
                    this.measureEntityUnderPointer(event);
                }
                else {
                    await this.controller.clearEntities();
                }
            });
        };
        this.controller = controller;
        this.measurableEntityTypes = measurableEntityTypes;
    }
    initialize(element, api) {
        this.element = element;
        this.api = api;
        this.rectObserver.observe(element);
        element.addEventListener('pointermove', this.handlePointerMove);
        element.addEventListener('pointerdown', this.handlePointerDown);
    }
    dispose() {
        var _a, _b, _c;
        this.rectObserver.disconnect();
        (_a = this.measurementInteraction) === null || _a === void 0 ? void 0 : _a.dispose();
        this.clearCursor();
        (_b = this.element) === null || _b === void 0 ? void 0 : _b.removeEventListener('pointermove', this.handlePointerMove);
        (_c = this.element) === null || _c === void 0 ? void 0 : _c.removeEventListener('pointerdown', this.handlePointerDown);
        this.element = undefined;
        this.api = undefined;
    }
    addCursor(cursor) {
        this.cursor = this.ifInitialized(({ api }) => api.addCursor(cursor));
    }
    clearCursor() {
        var _a;
        (_a = this.cursor) === null || _a === void 0 ? void 0 : _a.dispose();
        this.cursor = undefined;
    }
    async isMeasurableEntityUnderPointer(event) {
        var _a;
        const pt = getMouseClientPosition(event, this.elementRect);
        const type = await ((_a = this.api) === null || _a === void 0 ? void 0 : _a.getEntityTypeAtPoint(pt));
        return type != null && this.measurableEntityTypes.includes(type);
    }
    measureEntityUnderPointer(event) {
        this.ifInitialized(async ({ api }) => {
            const pt = getMouseClientPosition(event, this.elementRect);
            const [hit] = await api.hitItems(pt);
            const entity = hit != null ? MeasurementEntity.fromHit(hit) : undefined;
            if (entity != null) {
                await this.controller.addEntity(entity);
            }
            else {
                await this.controller.clearEntities();
            }
        });
    }
    ifInitialized(f) {
        if (this.element != null && this.api != null) {
            return f({ element: this.element, api: this.api });
        }
        else {
            throw new Error('Measurement interaction handler not initialized.');
        }
    }
    ifNoInteraction(event, f) {
        const startPos = Point.create(event.clientX, event.clientY);
        let didInteract = false;
        const handleMouseMove = (event) => {
            const pos = Point.create(event.clientX, event.clientY);
            const dis = Point.distance(startPos, pos);
            didInteract = dis > 2;
        };
        const handleMouseUp = () => {
            window.removeEventListener('pointermove', handleMouseMove);
            window.removeEventListener('pointerup', handleMouseUp);
            if (!didInteract) {
                f();
            }
        };
        window.addEventListener('pointermove', handleMouseMove);
        window.addEventListener('pointerup', handleMouseUp);
    }
}
//# sourceMappingURL=interactions.js.map
