/*
 * Application Insights JavaScript SDK - Core, 3.0.9
 * Copyright (c) Microsoft and contributors. All rights reserved.
 */


import dynamicProto from "@microsoft/dynamicproto-js";
import { createAllPromise, createPromise, doAwaitResponse } from "@nevware21/ts-async";
import { arrForEach, arrIndexOf, objDefine, safe, scheduleTimeout } from "@nevware21/ts-utils";
import { createDynamicConfig } from "../Config/DynamicConfig";
import { _DYN_ADD_NOTIFICATION_LIS1, _DYN_CANCEL, _DYN_IS_ASYNC, _DYN_IS_CHILD_EVT, _DYN_PUSH, _DYN_REMOVE_NOTIFICATION_0, _DYN_SPLICE, _DYN_UNLOAD, _DYN_WATCH } from "../__DynamicConstants";
import { STR_EVENTS_DISCARDED, STR_EVENTS_SEND_REQUEST, STR_EVENTS_SENT, STR_PERF_EVENT } from "./InternalConstants";
var defaultValues = {
    perfEvtsSendAll: false
};
function _runScheduledListeners(asyncNotifications) {
    asyncNotifications.h = null;
    var callbacks = asyncNotifications.cb;
    asyncNotifications.cb = [];
    arrForEach(callbacks, function (cb) {
        // Run the listener in a try-catch to ensure that a single listener failing doesn't prevent the others from running
        safe(cb.fn, [cb.arg]);
    });
}
// This function is used to combine the logic of running the listeners and handling the async notifications so that they don't
// create multiple timers if there are multiple async listeners.
function _runListeners(listeners, name, asyncNotifications, callback) {
    arrForEach(listeners, function (listener) {
        if (listener && listener[name]) {
            if (asyncNotifications) {
                // Schedule the callback to be called after the current call stack has cleared.
                asyncNotifications.cb[_DYN_PUSH /* @min:%2epush */]({
                    fn: callback,
                    arg: listener
                });
                asyncNotifications.h = asyncNotifications.h || scheduleTimeout(_runScheduledListeners, 0, asyncNotifications);
            }
            else {
                // Run the listener in a try-catch to ensure that a single listener failing doesn't prevent the others from running
                safe(callback, [listener]);
            }
        }
    });
}
/**
 * Class to manage sending notifications to all the listeners.
 */
var NotificationManager = /** @class */ (function () {
    function NotificationManager(config) {
        this.listeners = [];
        var perfEvtsSendAll;
        var unloadHandler;
        var _listeners = [];
        var _asyncNotifications = {
            h: null,
            cb: []
        };
        var cfgHandler = createDynamicConfig(config, defaultValues);
        unloadHandler = cfgHandler[_DYN_WATCH /* @min:%2ewatch */](function (details) {
            perfEvtsSendAll = !!details.cfg.perfEvtsSendAll;
        });
        dynamicProto(NotificationManager, this, function (_self) {
            objDefine(_self, "listeners", {
                g: function () { return _listeners; }
            });
            _self[_DYN_ADD_NOTIFICATION_LIS1 /* @min:%2eaddNotificationListener */] = function (listener) {
                _listeners[_DYN_PUSH /* @min:%2epush */](listener);
            };
            /**
             * Removes all instances of the listener.
             * @param listener - AWTNotificationListener to remove.
             */
            _self[_DYN_REMOVE_NOTIFICATION_0 /* @min:%2eremoveNotificationListener */] = function (listener) {
                var index = arrIndexOf(_listeners, listener);
                while (index > -1) {
                    _listeners[_DYN_SPLICE /* @min:%2esplice */](index, 1);
                    index = arrIndexOf(_listeners, listener);
                }
            };
            /**
             * Notification for events sent.
             * @param events - The array of events that have been sent.
             */
            _self[STR_EVENTS_SENT /* @min:%2eeventsSent */] = function (events) {
                _runListeners(_listeners, STR_EVENTS_SENT, _asyncNotifications, function (listener) {
                    listener[STR_EVENTS_SENT /* @min:%2eeventsSent */](events);
                });
            };
            /**
             * Notification for events being discarded.
             * @param events - The array of events that have been discarded by the SDK.
             * @param reason - The reason for which the SDK discarded the events. The EventsDiscardedReason
             * constant should be used to check the different values.
             */
            _self[STR_EVENTS_DISCARDED /* @min:%2eeventsDiscarded */] = function (events, reason) {
                _runListeners(_listeners, STR_EVENTS_DISCARDED, _asyncNotifications, function (listener) {
                    listener[STR_EVENTS_DISCARDED /* @min:%2eeventsDiscarded */](events, reason);
                });
            };
            /**
             * [Optional] A function called when the events have been requested to be sent to the sever.
             * @param sendReason - The reason why the event batch is being sent.
             * @param isAsync - A flag which identifies whether the requests are being sent in an async or sync manner.
             */
            _self[STR_EVENTS_SEND_REQUEST /* @min:%2eeventsSendRequest */] = function (sendReason, isAsync) {
                _runListeners(_listeners, STR_EVENTS_SEND_REQUEST, isAsync ? _asyncNotifications : null, function (listener) {
                    listener[STR_EVENTS_SEND_REQUEST /* @min:%2eeventsSendRequest */](sendReason, isAsync);
                });
            };
            _self[STR_PERF_EVENT /* @min:%2eperfEvent */] = function (perfEvent) {
                if (perfEvent) {
                    // Send all events or only parent events
                    if (perfEvtsSendAll || !perfEvent[_DYN_IS_CHILD_EVT /* @min:%2eisChildEvt */]()) {
                        _runListeners(_listeners, STR_PERF_EVENT, null, function (listener) {
                            if (perfEvent[_DYN_IS_ASYNC /* @min:%2eisAsync */]) {
                                scheduleTimeout(function () { return listener[STR_PERF_EVENT /* @min:%2eperfEvent */](perfEvent); }, 0);
                            }
                            else {
                                listener[STR_PERF_EVENT /* @min:%2eperfEvent */](perfEvent);
                            }
                        });
                    }
                }
            };
            _self[_DYN_UNLOAD /* @min:%2eunload */] = function (isAsync) {
                var _finishUnload = function () {
                    unloadHandler && unloadHandler.rm();
                    unloadHandler = null;
                    _listeners = [];
                    // Clear any async listener
                    _asyncNotifications.h && _asyncNotifications.h[_DYN_CANCEL /* @min:%2ecancel */]();
                    _asyncNotifications.h = null;
                    _asyncNotifications.cb = [];
                };
                var waiting;
                _runListeners(_listeners, "unload", null, function (listener) {
                    var asyncUnload = listener[_DYN_UNLOAD /* @min:%2eunload */](isAsync);
                    if (asyncUnload) {
                        if (!waiting) {
                            waiting = [];
                        }
                        waiting[_DYN_PUSH /* @min:%2epush */](asyncUnload);
                    }
                });
                if (waiting) {
                    return createPromise(function (resolve) {
                        return doAwaitResponse(createAllPromise(waiting), function () {
                            _finishUnload();
                            resolve();
                        });
                    });
                }
                else {
                    _finishUnload();
                }
            };
        });
    }
// Removed Stub for NotificationManager.prototype.addNotificationListener.
// Removed Stub for NotificationManager.prototype.removeNotificationListener.
// Removed Stub for NotificationManager.prototype.eventsSent.
// Removed Stub for NotificationManager.prototype.eventsDiscarded.
// Removed Stub for NotificationManager.prototype.eventsSendRequest.
// Removed Stub for NotificationManager.prototype.perfEvent.
// Removed Stub for NotificationManager.prototype.unload.
    // This is a workaround for an IE bug when using dynamicProto() with classes that don't have any
    // non-dynamic functions or static properties/functions when using uglify-js to minify the resulting code.
    NotificationManager.__ieDyn=1;

    return NotificationManager;
}());
export { NotificationManager };
//# sourceMappingURL=NotificationManager.js.map