import { Objects } from '@ephox/boulder';
import { Cell, Obj, Optional, Singleton } from '@ephox/katamari';
import { Compare } from '@ephox/sugar';
import { DelayedFunction } from '../alien/DelayedFunction';
import * as NativeEvents from '../api/events/NativeEvents';
import * as SystemEvents from '../api/events/SystemEvents';
const SIGNIFICANT_MOVE = 5;
const LONGPRESS_DELAY = 400;
const getTouch = (event) => {
    const raw = event.raw;
    if (raw.touches === undefined || raw.touches.length !== 1) {
        return Optional.none();
    }
    return Optional.some(raw.touches[0]);
};
// Check to see if the touch has changed a *significant* amount
const isFarEnough = (touch, data) => {
    const distX = Math.abs(touch.clientX - data.x);
    const distY = Math.abs(touch.clientY - data.y);
    return distX > SIGNIFICANT_MOVE || distY > SIGNIFICANT_MOVE;
};
const monitor = (settings) => {
    /* A tap event is a combination of touchstart and touchend on the same element
     * without a *significant* touchmove in between.
     */
    const startData = Singleton.value();
    const longpressFired = Cell(false);
    const longpress = DelayedFunction((event) => {
        settings.triggerEvent(SystemEvents.longpress(), event);
        longpressFired.set(true);
    }, LONGPRESS_DELAY);
    const handleTouchstart = (event) => {
        getTouch(event).each((touch) => {
            longpress.cancel();
            const data = {
                x: touch.clientX,
                y: touch.clientY,
                target: event.target
            };
            longpress.schedule(event);
            longpressFired.set(false);
            startData.set(data);
        });
        return Optional.none();
    };
    const handleTouchmove = (event) => {
        longpress.cancel();
        getTouch(event).each((touch) => {
            startData.on((data) => {
                if (isFarEnough(touch, data)) {
                    startData.clear();
                }
            });
        });
        return Optional.none();
    };
    const handleTouchend = (event) => {
        longpress.cancel();
        const isSame = (data) => Compare.eq(data.target, event.target);
        return startData.get().filter(isSame).map((_data) => {
            if (longpressFired.get()) {
                event.prevent();
                return false;
            }
            else {
                return settings.triggerEvent(SystemEvents.tap(), event);
            }
        });
    };
    const handlers = Objects.wrapAll([
        { key: NativeEvents.touchstart(), value: handleTouchstart },
        { key: NativeEvents.touchmove(), value: handleTouchmove },
        { key: NativeEvents.touchend(), value: handleTouchend }
    ]);
    const fireIfReady = (event, type) => Obj.get(handlers, type).bind((handler) => handler(event));
    return {
        fireIfReady
    };
};
export { monitor };
//# sourceMappingURL=TapEvent.js.map