import { generateId, createLinkedList, } from "@intelligentgraphics/ig.utilities";
import BaseLogger from "../Logger";
var Logger = BaseLogger.createSubLogger("NotificationCenter");
var ALL_NOTIFICATIONS_TOKEN = "ALL_NOTIFICATIONS_*[]*";
export var createNotificationCenter = function () {
    var listeners = createLinkedList();
    var createSubscription = function (data) {
        var id = data.id === undefined ? generateId() : data.id;
        return {
            id: id,
            send: function (event, data) { return send(id, event, data); },
            destroy: function () { return unsubscribe(id); },
        };
    };
    var any = function (callback, options) {
        if (options === void 0) { options = {}; }
        var subscription = createSubscription(options);
        listeners.push({
            id: subscription.id,
            callback: callback,
            event: ALL_NOTIFICATIONS_TOKEN,
        });
        return subscription;
    };
    var on = function (event, callback, options) {
        if (options === void 0) { options = {}; }
        Logger.info("subscribing", { event: event, options: options });
        var subscription = createSubscription(options);
        listeners.push({
            id: subscription.id,
            callback: callback,
            event: event,
        });
        return subscription;
    };
    var subscribe = function (on, options) {
        if (options === void 0) { options = {}; }
        Logger.info("subscribing", { options: options, on: on });
        var subscription = createSubscription(options);
        for (var event_1 in on) {
            listeners.push({
                id: subscription.id,
                event: event_1,
                callback: on[event_1],
            });
        }
        return subscription;
    };
    var unsubscribe = function (subscriber, notification) {
        Logger.info("Unsubscribe", { subscriber: subscriber, notification: notification });
        listeners.consumeAll(function (item) {
            if (notification === undefined) {
                return item.id === subscriber;
            }
            return item.id === subscriber && item.event === notification;
        });
    };
    var send = function (sender, notification, data) {
        Logger.info("sending", {
            type: notification,
            data: data,
            sender: sender,
        });
        var eventData;
        listeners.forEach(function (_a) {
            var id = _a.id, callback = _a.callback, event = _a.event;
            if (
            // do not notify the sender itself
            sender === id ||
                (event !== ALL_NOTIFICATIONS_TOKEN && event !== notification)) {
                return;
            }
            if (eventData === undefined) {
                eventData = typeof data === "function" ? data() : data;
            }
            if (event === ALL_NOTIFICATIONS_TOKEN) {
                try {
                    callback({
                        event: notification,
                        data: data,
                        sender: sender,
                    });
                }
                catch (err) {
                    Logger.error(err);
                }
                return;
            }
            try {
                callback(eventData, sender);
            }
            catch (err) {
                Logger.error(err);
            }
        });
    };
    var destroy = function () {
        listeners.clear();
    };
    return {
        destroy: destroy,
        any: any,
        on: on,
        subscribe: subscribe,
        unsubscribe: unsubscribe,
        send: send,
    };
};
export * from "./Subscription";
