import { __awaiter, __extends, __generator, __spreadArrays } from "tslib";
import { AnalyticsBrowser } from './browser';
import { resolveAliasArguments, resolveArguments, resolvePageArguments, resolveUserArguments, } from './core/arguments-resolver';
import { invokeCallback } from './core/callback';
import { isOffline } from './core/connection';
import { Context } from './core/context';
import { Emitter } from './core/emitter';
import { EventFactory } from './core/events';
import { EventQueue } from './core/queue/event-queue';
import { Group, User } from './core/user';
import autoBind from './lib/bind-all';
import { PersistedPriorityQueue } from './lib/priority-queue/persisted';
var deprecationWarning = 'This is being deprecated and will be not be available in future releases of Analytics JS';
// reference any pre-existing "analytics" object so a user can restore the reference
// eslint-disable-next-line @typescript-eslint/no-explicit-any
var globalAny = global;
var _analytics = globalAny.analytics;
var Analytics = /** @class */ (function (_super) {
    __extends(Analytics, _super);
    function Analytics(settings, options, queue, user, group) {
        var _a, _b;
        var _this = _super.call(this) || this;
        _this._debug = false;
        _this.initialized = false;
        _this.user = function () {
            return _this._user;
        };
        _this.init = _this.initialize.bind(_this);
        var cookieOptions = options === null || options === void 0 ? void 0 : options.cookie;
        _this.settings = settings;
        _this.settings.timeout = (_a = _this.settings.timeout) !== null && _a !== void 0 ? _a : 300;
        _this.queue = queue !== null && queue !== void 0 ? queue : new EventQueue(new PersistedPriorityQueue((options === null || options === void 0 ? void 0 : options.retryQueue) ? 4 : 1, 'event-queue'));
        _this._user = user !== null && user !== void 0 ? user : new User(options === null || options === void 0 ? void 0 : options.user, cookieOptions).load();
        _this._group = group !== null && group !== void 0 ? group : new Group(options === null || options === void 0 ? void 0 : options.group, cookieOptions).load();
        _this.eventFactory = new EventFactory(_this._user);
        _this.integrations = (_b = options === null || options === void 0 ? void 0 : options.integrations) !== null && _b !== void 0 ? _b : {};
        _this.options = options !== null && options !== void 0 ? options : {};
        autoBind(_this);
        return _this;
    }
    Analytics.prototype.track = function () {
        var args = [];
        for (var _i = 0; _i < arguments.length; _i++) {
            args[_i] = arguments[_i];
        }
        return __awaiter(this, void 0, void 0, function () {
            var _a, name, data, opts, cb, segmentEvent;
            return __generator(this, function (_b) {
                _a = resolveArguments.apply(void 0, args), name = _a[0], data = _a[1], opts = _a[2], cb = _a[3];
                segmentEvent = this.eventFactory.track(name, data, opts, this.integrations);
                this.emit('track', name, data, opts);
                return [2 /*return*/, this.dispatch(segmentEvent, cb)];
            });
        });
    };
    Analytics.prototype.page = function () {
        var args = [];
        for (var _i = 0; _i < arguments.length; _i++) {
            args[_i] = arguments[_i];
        }
        return __awaiter(this, void 0, void 0, function () {
            var _a, category, page, properties, options, callback, segmentEvent;
            return __generator(this, function (_b) {
                _a = resolvePageArguments.apply(void 0, args), category = _a[0], page = _a[1], properties = _a[2], options = _a[3], callback = _a[4];
                segmentEvent = this.eventFactory.page(category, page, properties, options, this.integrations);
                this.emit('page', category, name, properties, options);
                return [2 /*return*/, this.dispatch(segmentEvent, callback)];
            });
        });
    };
    Analytics.prototype.identify = function () {
        var args = [];
        for (var _i = 0; _i < arguments.length; _i++) {
            args[_i] = arguments[_i];
        }
        return __awaiter(this, void 0, void 0, function () {
            var _a, id, _traits, options, callback, segmentEvent;
            return __generator(this, function (_b) {
                _a = resolveUserArguments(this._user).apply(void 0, args), id = _a[0], _traits = _a[1], options = _a[2], callback = _a[3];
                this._user.identify(id, _traits);
                segmentEvent = this.eventFactory.identify(this._user.id(), this._user.traits(), options, this.integrations);
                this.emit('identify', this._user.id(), this._user.traits(), options);
                return [2 /*return*/, this.dispatch(segmentEvent, callback)];
            });
        });
    };
    Analytics.prototype.group = function () {
        var args = [];
        for (var _i = 0; _i < arguments.length; _i++) {
            args[_i] = arguments[_i];
        }
        if (args.length === 0) {
            return this._group;
        }
        var _a = resolveUserArguments(this._group).apply(void 0, args), id = _a[0], _traits = _a[1], options = _a[2], callback = _a[3];
        this._group.identify(id, _traits);
        var groupId = this._group.id();
        var groupdTraits = this._group.traits();
        var segmentEvent = this.eventFactory.group(groupId, groupdTraits, options, this.integrations);
        this.emit('group', groupId, groupdTraits, options);
        return this.dispatch(segmentEvent, callback);
    };
    Analytics.prototype.alias = function () {
        var args = [];
        for (var _i = 0; _i < arguments.length; _i++) {
            args[_i] = arguments[_i];
        }
        return __awaiter(this, void 0, void 0, function () {
            var _a, to, from, options, callback, segmentEvent;
            return __generator(this, function (_b) {
                _a = resolveAliasArguments.apply(void 0, args), to = _a[0], from = _a[1], options = _a[2], callback = _a[3];
                segmentEvent = this.eventFactory.alias(to, from, options, this.integrations);
                this.emit('alias', to, from, options);
                return [2 /*return*/, this.dispatch(segmentEvent, callback)];
            });
        });
    };
    Analytics.prototype.screen = function () {
        var args = [];
        for (var _i = 0; _i < arguments.length; _i++) {
            args[_i] = arguments[_i];
        }
        return __awaiter(this, void 0, void 0, function () {
            var _a, category, page, properties, options, callback, segmentEvent;
            return __generator(this, function (_b) {
                _a = resolvePageArguments.apply(void 0, args), category = _a[0], page = _a[1], properties = _a[2], options = _a[3], callback = _a[4];
                segmentEvent = this.eventFactory.screen(category, page, properties, options, this.integrations);
                this.emit('screen', category, name, properties, options);
                return [2 /*return*/, this.dispatch(segmentEvent, callback)];
            });
        });
    };
    Analytics.prototype.trackClick = function () {
        var args = [];
        for (var _i = 0; _i < arguments.length; _i++) {
            args[_i] = arguments[_i];
        }
        return __awaiter(this, void 0, void 0, function () {
            var autotrack;
            var _a;
            return __generator(this, function (_b) {
                switch (_b.label) {
                    case 0: return [4 /*yield*/, import(
                        /* webpackChunkName: "auto-track" */ './core/auto-track')];
                    case 1:
                        autotrack = _b.sent();
                        return [2 /*return*/, (_a = autotrack.link).call.apply(_a, __spreadArrays([this], args))];
                }
            });
        });
    };
    Analytics.prototype.trackLink = function () {
        var args = [];
        for (var _i = 0; _i < arguments.length; _i++) {
            args[_i] = arguments[_i];
        }
        return __awaiter(this, void 0, void 0, function () {
            var autotrack;
            var _a;
            return __generator(this, function (_b) {
                switch (_b.label) {
                    case 0: return [4 /*yield*/, import(
                        /* webpackChunkName: "auto-track" */ './core/auto-track')];
                    case 1:
                        autotrack = _b.sent();
                        return [2 /*return*/, (_a = autotrack.link).call.apply(_a, __spreadArrays([this], args))];
                }
            });
        });
    };
    Analytics.prototype.trackSubmit = function () {
        var args = [];
        for (var _i = 0; _i < arguments.length; _i++) {
            args[_i] = arguments[_i];
        }
        return __awaiter(this, void 0, void 0, function () {
            var autotrack;
            var _a;
            return __generator(this, function (_b) {
                switch (_b.label) {
                    case 0: return [4 /*yield*/, import(
                        /* webpackChunkName: "auto-track" */ './core/auto-track')];
                    case 1:
                        autotrack = _b.sent();
                        return [2 /*return*/, (_a = autotrack.form).call.apply(_a, __spreadArrays([this], args))];
                }
            });
        });
    };
    Analytics.prototype.trackForm = function () {
        var args = [];
        for (var _i = 0; _i < arguments.length; _i++) {
            args[_i] = arguments[_i];
        }
        return __awaiter(this, void 0, void 0, function () {
            var autotrack;
            var _a;
            return __generator(this, function (_b) {
                switch (_b.label) {
                    case 0: return [4 /*yield*/, import(
                        /* webpackChunkName: "auto-track" */ './core/auto-track')];
                    case 1:
                        autotrack = _b.sent();
                        return [2 /*return*/, (_a = autotrack.form).call.apply(_a, __spreadArrays([this], args))];
                }
            });
        });
    };
    Analytics.prototype.register = function () {
        var plugins = [];
        for (var _i = 0; _i < arguments.length; _i++) {
            plugins[_i] = arguments[_i];
        }
        return __awaiter(this, void 0, void 0, function () {
            var ctx, registrations;
            var _this = this;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        ctx = Context.system();
                        registrations = plugins.map(function (xt) {
                            return _this.queue.register(ctx, xt, _this);
                        });
                        return [4 /*yield*/, Promise.all(registrations)];
                    case 1:
                        _a.sent();
                        return [2 /*return*/, ctx];
                }
            });
        });
    };
    Analytics.prototype.deregister = function () {
        var plugins = [];
        for (var _i = 0; _i < arguments.length; _i++) {
            plugins[_i] = arguments[_i];
        }
        return __awaiter(this, void 0, void 0, function () {
            var ctx, deregistrations;
            var _this = this;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        ctx = Context.system();
                        deregistrations = plugins.map(function (pl) { return __awaiter(_this, void 0, void 0, function () {
                            var plugin;
                            return __generator(this, function (_a) {
                                plugin = this.queue.plugins.find(function (p) { return p.name === pl; });
                                if (plugin) {
                                    return [2 /*return*/, this.queue.deregister(ctx, plugin, this)];
                                }
                                else {
                                    ctx.log('warn', "plugin " + pl + " not found");
                                }
                                return [2 /*return*/];
                            });
                        }); });
                        return [4 /*yield*/, Promise.all(deregistrations)];
                    case 1:
                        _a.sent();
                        return [2 /*return*/, ctx];
                }
            });
        });
    };
    Analytics.prototype.debug = function (toggle) {
        this._debug = toggle;
        return this;
    };
    Analytics.prototype.reset = function () {
        this._user.reset();
    };
    Analytics.prototype.timeout = function (timeout) {
        this.settings.timeout = timeout;
    };
    Analytics.prototype.dispatch = function (event, callback) {
        return __awaiter(this, void 0, void 0, function () {
            var ctx, dispatched;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        ctx = new Context(event);
                        if (isOffline() && !this.options.retryQueue) {
                            return [2 /*return*/, ctx];
                        }
                        if (!this.queue.isEmpty()) return [3 /*break*/, 2];
                        return [4 /*yield*/, this.queue.dispatchSingle(ctx)];
                    case 1:
                        dispatched = _a.sent();
                        return [3 /*break*/, 4];
                    case 2: return [4 /*yield*/, this.queue.dispatch(ctx)];
                    case 3:
                        dispatched = _a.sent();
                        _a.label = 4;
                    case 4:
                        if (!callback) return [3 /*break*/, 6];
                        return [4 /*yield*/, invokeCallback(dispatched, callback, this.settings.timeout)];
                    case 5:
                        dispatched = _a.sent();
                        _a.label = 6;
                    case 6:
                        if (this._debug) {
                            dispatched.flush();
                        }
                        return [2 /*return*/, dispatched];
                }
            });
        });
    };
    Analytics.prototype.addSourceMiddleware = function (fn) {
        return __awaiter(this, void 0, void 0, function () {
            var sourceMiddlewarePlugin, plugin;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0: return [4 /*yield*/, import(
                        /* webpackChunkName: "middleware" */ './plugins/middleware')];
                    case 1:
                        sourceMiddlewarePlugin = (_a.sent()).sourceMiddlewarePlugin;
                        plugin = sourceMiddlewarePlugin(fn);
                        return [4 /*yield*/, this.register(plugin)];
                    case 2:
                        _a.sent();
                        return [2 /*return*/, this];
                }
            });
        });
    };
    Analytics.prototype.addDestinationMiddleware = function (integrationName) {
        var middlewares = [];
        for (var _i = 1; _i < arguments.length; _i++) {
            middlewares[_i - 1] = arguments[_i];
        }
        return __awaiter(this, void 0, void 0, function () {
            var legacyDestinations;
            return __generator(this, function (_a) {
                legacyDestinations = this.queue.plugins.filter(function (xt) {
                    // xt instanceof LegacyDestination &&
                    return xt.name.toLowerCase() === integrationName.toLowerCase();
                });
                legacyDestinations.forEach(function (destination) {
                    destination.addMiddleware.apply(destination, middlewares);
                });
                return [2 /*return*/, this];
            });
        });
    };
    Analytics.prototype.setAnonymousId = function (id) {
        return this._user.anonymousId(id);
    };
    Analytics.prototype.queryString = function (query) {
        return __awaiter(this, void 0, void 0, function () {
            var queryString;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0: return [4 /*yield*/, import(
                        /* webpackChunkName: "queryString" */ './core/query-string')];
                    case 1:
                        queryString = (_a.sent()).queryString;
                        return [2 /*return*/, queryString(this, query)];
                }
            });
        });
    };
    /**
     * @deprecated This function does not register a destination plugin.
     *
     * Instantiates a legacy Analytics.js destination.
     *
     * This function does not register the destination as an Analytics.JS plugin,
     * all the it does it to invoke the factory function back.
     */
    Analytics.prototype.use = function (legacyPluginFactory) {
        legacyPluginFactory(this);
        return this;
    };
    Analytics.prototype.ready = function (callback) {
        if (callback === void 0) { callback = function (res) { return res; }; }
        return __awaiter(this, void 0, void 0, function () {
            return __generator(this, function (_a) {
                return [2 /*return*/, Promise.all(this.queue.plugins.map(function (i) { return (i.ready ? i.ready() : Promise.resolve()); })).then(function (res) {
                        callback(res);
                        return res;
                    })];
            });
        });
    };
    // analytics-classic api
    Analytics.prototype.noConflict = function () {
        console.warn(deprecationWarning);
        window.analytics = _analytics !== null && _analytics !== void 0 ? _analytics : this;
        return this;
    };
    Analytics.prototype.normalize = function (msg) {
        console.warn(deprecationWarning);
        return this.eventFactory.normalize(msg);
    };
    Object.defineProperty(Analytics.prototype, "failedInitializations", {
        get: function () {
            console.warn(deprecationWarning);
            return this.queue.failedInitializations;
        },
        enumerable: false,
        configurable: true
    });
    Object.defineProperty(Analytics.prototype, "VERSION", {
        get: function () {
            var _a;
            console.warn(deprecationWarning);
            return (_a = process.env.VERSION) !== null && _a !== void 0 ? _a : '';
        },
        enumerable: false,
        configurable: true
    });
    Analytics.prototype.initialize = function (settings, options) {
        return __awaiter(this, void 0, void 0, function () {
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        console.warn(deprecationWarning);
                        if (!settings) return [3 /*break*/, 2];
                        return [4 /*yield*/, AnalyticsBrowser.load(settings, options)];
                    case 1:
                        _a.sent();
                        _a.label = 2;
                    case 2:
                        this.options = options || {};
                        return [2 /*return*/, this];
                }
            });
        });
    };
    Analytics.prototype.pageview = function (url) {
        return __awaiter(this, void 0, void 0, function () {
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        console.warn(deprecationWarning);
                        return [4 /*yield*/, this.page({ path: url })];
                    case 1:
                        _a.sent();
                        return [2 /*return*/, this];
                }
            });
        });
    };
    Object.defineProperty(Analytics.prototype, "plugins", {
        get: function () {
            var _a;
            console.warn(deprecationWarning);
            // @ts-expect-error
            return (_a = this._plugins) !== null && _a !== void 0 ? _a : {};
        },
        enumerable: false,
        configurable: true
    });
    Object.defineProperty(Analytics.prototype, "Integrations", {
        get: function () {
            console.warn(deprecationWarning);
            var integrations = this.queue.plugins
                .filter(function (plugin) { return plugin.type === 'destination'; })
                .reduce(function (acc, plugin) {
                var name = plugin.name
                    .toLowerCase()
                    .replace('.', '')
                    .split(' ')
                    .join('-') + "Integration";
                // @ts-expect-error
                var integration = window[name];
                if (!integration) {
                    return acc;
                }
                var nested = integration.Integration; // hack - Google Analytics function resides in the "Integration" field
                if (nested) {
                    acc[plugin.name] = nested;
                    return acc;
                }
                acc[plugin.name] = integration;
                return acc;
            }, {});
            return integrations;
        },
        enumerable: false,
        configurable: true
    });
    // analytics-classic stubs
    Analytics.prototype.log = function () {
        console.warn(deprecationWarning);
        return;
    };
    Analytics.prototype.addIntegrationMiddleware = function () {
        console.warn(deprecationWarning);
        return;
    };
    Analytics.prototype.listeners = function () {
        console.warn(deprecationWarning);
        return;
    };
    Analytics.prototype.addEventListener = function () {
        console.warn(deprecationWarning);
        return;
    };
    Analytics.prototype.removeAllListeners = function () {
        console.warn(deprecationWarning);
        return;
    };
    Analytics.prototype.removeListener = function () {
        console.warn(deprecationWarning);
        return;
    };
    Analytics.prototype.removeEventListener = function () {
        console.warn(deprecationWarning);
        return;
    };
    Analytics.prototype.hasListeners = function () {
        console.warn(deprecationWarning);
        return;
    };
    // This function is only used to add GA and Appcue, but these are already being added to Integrations by AJSN
    Analytics.prototype.addIntegration = function () {
        console.warn(deprecationWarning);
        return;
    };
    Analytics.prototype.add = function () {
        console.warn(deprecationWarning);
        return;
    };
    // snippet function
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    Analytics.prototype.push = function (args) {
        // eslint-disable-next-line @typescript-eslint/no-explicit-any
        var an = this;
        var method = args.shift();
        if (method) {
            if (!an[method])
                return;
        }
        an[method].apply(this, args);
    };
    return Analytics;
}(Emitter));
export { Analytics };
//# sourceMappingURL=analytics.js.map