import Vector2 from "../../../../core/geom/Vector2.js";
import { getTouchCenter } from "./getTouchCenter.js";

/**
 *
 * @param {TouchList} touchList
 * @param {function(Touch,number)} callback
 */
function forEachTouch(touchList, callback) {
    const length = touchList.length;
    for (let i = 0; i < length; i++) {
        const touch = touchList.item(i);
        callback(touch, i);
    }
}

/**
 *
 * @param {Signal} touchStart
 * @param {Signal} touchEnd
 * @param {Signal} touchMove
 * @param {Signal} pinch
 * @param {Signal} pinchStart
 * @param {Signal} pinchEnd
 * @param {PointerDevice} device
 */
export function observePinch({
                          touchStart,
                          touchEnd,
                          touchMove,
                          pinch,
                          pinchStart,
                          pinchEnd,
                          device
                      }) {
    const center = new Vector2();

    const v2 = new Vector2();

    const pinchBox0 = new Vector2();
    const pinchBox1 = new Vector2();

    let pinchActive = false;
    let touchCount = 0;


    /**
     *
     * @param {TouchList} touchList
     * @param {Vector2} pinchDimensions
     */
    function computeTouchRadius(touchList, pinchDimensions) {
        getTouchCenter(touchList, center);

        const length = touchList.length;

        pinchDimensions.set(0, 0);

        for (let i = 0; i < length; i++) {
            const touch = touchList.item(i);

            device.readPointerPositionFromEvent(v2, touch);

            v2.sub(center);
            v2.abs();

            pinchDimensions.add(v2);
        }

        return pinchDimensions.multiplyScalar(1 / length);
    }

    function touchRemoved(touch, event) {
        touchCount--;
        if (touchCount < 2 && pinchActive) {
            handlePinchEnd(event);
        }
    }

    function touchAdded(touch, event) {
        touchCount++;
        if (touchCount > 1 && !pinchActive) {
            handlePinchStart(event);
        }
    }

    function handlePinchStart(event) {
        pinchActive = true;

        computeTouchRadius(event.touches, pinchBox0);

        touchMove.add(handleMove);

        pinchStart.send1(pinchBox0);
    }

    /**
     *
     * @param {TouchEvent} event
     */
    function handlePinchEnd(event) {
        pinchActive = false;

        touchMove.remove(handleMove);

        pinchEnd.send0();
    }

    function handleDown(position, event) {
        forEachTouch(event.changedTouches, function (touch) {
            touchAdded(touch, event);
        });
    }

    function handleUp(position, event) {
        forEachTouch(event.changedTouches, function (touch) {
            touchRemoved(touch, event);
        });
    }

    function handleMove(position, event) {
        computeTouchRadius(event.touches, pinchBox1);
        pinch.send2(pinchBox1, pinchBox0);
    }

    touchEnd.add(handleUp);
    touchStart.add(handleDown);
}