/*!
 * Copyright (c) 2026 Vertex Software LLC. All rights reserved.
 */
import { Angle, Matrix2, Point } from "@vertexvis/geometry";
import { requestAnimationFrame } from "../window";
export class MultiTouchInteractionHandler {
    constructor() {
        this.previousFirstPoints = [];
        this.previousSecondPoints = [];
    }
    initialize(element, api) {
        this.element = element;
        this.interactionApi = api;
    }
    dispose() {
        this.element = undefined;
    }
    beginTwoPointTouch(point1, point2) {
        this.previousFirstPoints = [...this.previousFirstPoints, point1];
        this.previousSecondPoints = [...this.previousSecondPoints, point2];
    }
    handleTwoPointTouchMove(point1, point2) {
        this.previousFirstPoints = [...this.previousFirstPoints, point1];
        this.previousSecondPoints = [...this.previousSecondPoints, point2];
        // Process updates to touch points on animation frame callbacks to batch
        // the processing. Because each event can potentially only represent a single
        // touch point moving, two opposing angles can be computed sequentially. This
        // results in a wobbling effect if those angles are both sent, and this batched
        // processing helps to reduce that effect.
        requestAnimationFrame(() => {
            var _a, _b, _c, _d;
            if (this.previousFirstPoints.length > 1 &&
                this.previousSecondPoints.length > 1 &&
                this.previousFirstPoints.length === this.previousSecondPoints.length) {
                const previousFirstPoints = this.previousFirstPoints;
                const previousSecondPoints = this.previousSecondPoints;
                this.previousFirstPoints = this.previousFirstPoints.slice(-1);
                this.previousSecondPoints = this.previousSecondPoints.slice(-1);
                const changes = previousFirstPoints.reduce((result, previousFirstPoint, i) => {
                    if (i < previousFirstPoints.length - 1) {
                        const firstPoint = previousFirstPoints[i + 1];
                        const previousSecondPoint = previousSecondPoints[i];
                        const secondPoint = previousSecondPoints[i + 1];
                        return {
                            deltas: [
                                ...result.deltas,
                                this.computeDelta(previousFirstPoint, previousSecondPoint, firstPoint, secondPoint),
                            ],
                            zooms: [
                                ...result.zooms,
                                this.computeZoom(previousFirstPoint, previousSecondPoint, firstPoint, secondPoint),
                            ],
                            angles: [
                                ...result.angles,
                                this.computeAngle(previousFirstPoint, previousSecondPoint, firstPoint, secondPoint),
                            ],
                        };
                    }
                    return result;
                }, {
                    deltas: [],
                    zooms: [],
                    angles: [],
                });
                const delta = changes.deltas.reduce((r, d) => Point.add(r, d), Point.create());
                const zoom = changes.zooms.reduce((z, d) => z + d, 0);
                const angle = changes.angles.reduce((a, d) => a + d, 0);
                const center = Point.create((previousFirstPoints[previousFirstPoints.length - 1].x +
                    previousSecondPoints[previousSecondPoints.length - 1].x) /
                    2, (previousFirstPoints[previousFirstPoints.length - 1].y +
                    previousSecondPoints[previousSecondPoints.length - 1].y) /
                    2);
                (_a = this.interactionApi) === null || _a === void 0 ? void 0 : _a.beginInteraction();
                (_b = this.interactionApi) === null || _b === void 0 ? void 0 : _b.zoomCameraToPoint(center, zoom);
                (_c = this.interactionApi) === null || _c === void 0 ? void 0 : _c.panCameraByDelta(delta);
                (_d = this.interactionApi) === null || _d === void 0 ? void 0 : _d.twistCamera(angle);
            }
        });
    }
    endTwoPointTouch() {
        this.previousFirstPoints = [];
        this.previousSecondPoints = [];
    }
    computeDelta(previousPoint1, previousPoint2, point1, point2) {
        return Point.add(Point.subtract(point1, previousPoint1), Point.subtract(point2, previousPoint2));
    }
    computeZoom(previousPoint1, previousPoint2, point1, point2) {
        const distance = Point.distance(point1, point2) -
            Point.distance(previousPoint1, previousPoint2);
        return distance * 0.5;
    }
    computeAngle(previousPoint1, previousPoint2, point1, point2) {
        const previousToCurrent = Matrix2.create(Point.subtract(previousPoint1, previousPoint2), Point.subtract(point1, point2));
        return Angle.toDegrees(Math.atan2(Matrix2.determinant(previousToCurrent), Matrix2.dot(previousToCurrent)));
    }
}
//# sourceMappingURL=multiTouchInteractionHandler.js.map
