import { Arr, Singleton } from '@ephox/katamari';
import { DomEvent, SelectorExists, SugarNode } from '@ephox/sugar';
import * as Keys from '../alien/Keys';
import * as SystemEvents from '../api/events/SystemEvents';
import * as TapEvent from './TapEvent';
const isDangerous = (event) => {
    // Will trigger the Back button in the browser
    const keyEv = event.raw;
    return keyEv.which === Keys.BACKSPACE[0] && !Arr.contains(['input', 'textarea'], SugarNode.name(event.target)) && !SelectorExists.closest(event.target, '[contenteditable="true"]');
};
const setup = (container, rawSettings) => {
    const settings = {
        stopBackspace: true,
        ...rawSettings
    };
    const pointerEvents = [
        'touchstart',
        'touchmove',
        'touchend',
        'touchcancel',
        'gesturestart',
        'mousedown',
        'mouseup',
        'mouseover',
        'mousemove',
        'mouseout',
        'click'
    ];
    const tapEvent = TapEvent.monitor(settings);
    // These events are just passed through ... no additional processing
    const simpleEvents = Arr.map(pointerEvents.concat([
        'selectstart',
        'input',
        'contextmenu',
        'change',
        'transitionend',
        'transitioncancel',
        // Test the drag events
        'drag',
        'dragstart',
        'dragend',
        'dragenter',
        'dragleave',
        'dragover',
        'drop',
        'keyup'
    ]), (type) => DomEvent.bind(container, type, (event) => {
        tapEvent.fireIfReady(event, type).each((tapStopped) => {
            if (tapStopped) {
                event.kill();
            }
        });
        const stopped = settings.triggerEvent(type, event);
        if (stopped) {
            event.kill();
        }
    }));
    const pasteTimeout = Singleton.value();
    const onPaste = DomEvent.bind(container, 'paste', (event) => {
        tapEvent.fireIfReady(event, 'paste').each((tapStopped) => {
            if (tapStopped) {
                event.kill();
            }
        });
        const stopped = settings.triggerEvent('paste', event);
        if (stopped) {
            event.kill();
        }
        pasteTimeout.set(setTimeout(() => {
            settings.triggerEvent(SystemEvents.postPaste(), event);
        }, 0));
    });
    const onKeydown = DomEvent.bind(container, 'keydown', (event) => {
        // Prevent default of backspace when not in input fields.
        const stopped = settings.triggerEvent('keydown', event);
        if (stopped) {
            event.kill();
        }
        else if (settings.stopBackspace && isDangerous(event)) {
            event.prevent();
        }
    });
    const onFocusIn = DomEvent.bind(container, 'focusin', (event) => {
        const stopped = settings.triggerEvent('focusin', event);
        if (stopped) {
            event.kill();
        }
    });
    const focusoutTimeout = Singleton.value();
    const onFocusOut = DomEvent.bind(container, 'focusout', (event) => {
        const stopped = settings.triggerEvent('focusout', event);
        if (stopped) {
            event.kill();
        }
        // INVESTIGATE: Come up with a better way of doing this. Related target can be used, but not on FF.
        // It allows the active element to change before firing the blur that we will listen to
        // for things like closing popups
        focusoutTimeout.set(setTimeout(() => {
            settings.triggerEvent(SystemEvents.postBlur(), event);
        }, 0));
    });
    const unbind = () => {
        Arr.each(simpleEvents, (e) => {
            e.unbind();
        });
        onKeydown.unbind();
        onFocusIn.unbind();
        onFocusOut.unbind();
        onPaste.unbind();
        pasteTimeout.on(clearTimeout);
        focusoutTimeout.on(clearTimeout);
    };
    return {
        unbind
    };
};
export { setup };
//# sourceMappingURL=GuiEvents.js.map