import { Obj } from '@ephox/katamari';
import { TransformFind } from '@ephox/sugar';
import * as Tagger from '../registry/Tagger';
import * as DescribedHandler from './DescribedHandler';
const eventHandler = (element, descHandler) => ({
    element,
    descHandler
});
const broadcastHandler = (id, handler) => ({
    id,
    descHandler: handler
});
export const EventRegistry = () => {
    const registry = {};
    const registerId = (extraArgs, id, events) => {
        Obj.each(events, (v, k) => {
            const handlers = registry[k] !== undefined ? registry[k] : {};
            handlers[id] = DescribedHandler.curryArgs(v, extraArgs);
            registry[k] = handlers;
        });
    };
    const findHandler = (handlers, elem) => Tagger.read(elem)
        .bind((id) => Obj.get(handlers, id))
        .map((descHandler) => eventHandler(elem, descHandler));
    // Given just the event type, find all handlers regardless of element
    const filterByType = (type) => Obj.get(registry, type)
        .map((handlers) => Obj.mapToArray(handlers, (f, id) => broadcastHandler(id, f)))
        .getOr([]);
    // Given event type, and element, find the handler.
    const find = (isAboveRoot, type, target) => Obj.get(registry, type)
        .bind((handlers) => TransformFind.closest(target, (elem) => findHandler(handlers, elem), isAboveRoot));
    const unregisterId = (id) => {
        // INVESTIGATE: Find a better way than mutation if we can.
        Obj.each(registry, (handlersById, _eventName) => {
            if (Obj.has(handlersById, id)) {
                delete handlersById[id];
            }
        });
    };
    return {
        registerId,
        unregisterId,
        filterByType,
        find
    };
};
//# sourceMappingURL=EventRegistry.js.map