"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.EventCompressor = void 0;
var analytics_client_common_1 = require("@amplitude/analytics-client-common");
var rrweb_packer_1 = require("@amplitude/rrweb-packer");
var DEFAULT_TIMEOUT = 2000;
var EventCompressor = /** @class */ (function () {
    function EventCompressor(eventsManager, config, deviceId, workerScriptInternal) {
        var _this = this;
        var _a, _b, _c;
        this.taskQueue = [];
        this.isProcessing = false;
        this.compressEvent = function (event) {
            var packedEvent = (0, rrweb_packer_1.pack)(event);
            return JSON.stringify(packedEvent);
        };
        this.addCompressedEventToManager = function (compressedEvent, sessionId) {
            if (_this.eventsManager && _this.deviceId) {
                _this.eventsManager.addEvent({
                    event: { type: 'replay', data: compressedEvent },
                    sessionId: sessionId,
                    deviceId: _this.deviceId,
                });
            }
        };
        this.addCompressedEvent = function (event, sessionId) {
            if (_this.worker) {
                // This indirectly compresses the event.
                _this.worker.postMessage({ event: event, sessionId: sessionId });
            }
            else {
                var compressedEvent = _this.compressEvent(event);
                _this.addCompressedEventToManager(compressedEvent, sessionId);
            }
        };
        this.terminate = function () {
            var _a;
            (_a = _this.worker) === null || _a === void 0 ? void 0 : _a.terminate();
        };
        var globalScope = (0, analytics_client_common_1.getGlobalScope)();
        this.canUseIdleCallback = globalScope && 'requestIdleCallback' in globalScope;
        this.eventsManager = eventsManager;
        this.config = config;
        this.deviceId = deviceId;
        this.timeout = ((_a = config.performanceConfig) === null || _a === void 0 ? void 0 : _a.timeout) || DEFAULT_TIMEOUT;
        // These two lines will be changed at compile time.
        var replace = {};
        // This next line is going to be ridiculously hard to cover in unit tests, ignoring.
        /* istanbul ignore next */
        var workerScript = (_b = replace.COMPRESSION_WEBWORKER_BODY) !== null && _b !== void 0 ? _b : workerScriptInternal;
        if (((_c = this.config.experimental) === null || _c === void 0 ? void 0 : _c.useWebWorker) && globalScope && globalScope.Worker && workerScript) {
            config.loggerProvider.log('[Experimental] Enabling web worker for compression');
            var worker = new Worker(URL.createObjectURL(new Blob([workerScript], { type: 'application/javascript' })));
            worker.onerror = function (e) {
                config.loggerProvider.error(e);
            };
            worker.onmessage = function (e) {
                var _a = e.data, compressedEvent = _a.compressedEvent, sessionId = _a.sessionId;
                _this.addCompressedEventToManager(compressedEvent, sessionId);
            };
            this.worker = worker;
        }
    }
    // Schedule processing during idle time
    EventCompressor.prototype.scheduleIdleProcessing = function () {
        var _this = this;
        if (!this.isProcessing) {
            this.isProcessing = true;
            requestIdleCallback(function (idleDeadline) {
                _this.processQueue(idleDeadline);
            }, { timeout: this.timeout });
        }
    };
    // Add an event to the task queue if idle callback is supported or compress the event directly
    EventCompressor.prototype.enqueueEvent = function (event, sessionId) {
        var _a;
        if (this.canUseIdleCallback && ((_a = this.config.performanceConfig) === null || _a === void 0 ? void 0 : _a.enabled)) {
            this.config.loggerProvider.debug('Enqueuing event for processing during idle time.');
            this.taskQueue.push({ event: event, sessionId: sessionId });
            this.scheduleIdleProcessing();
        }
        else {
            this.config.loggerProvider.debug('Processing event without idle callback.');
            this.addCompressedEvent(event, sessionId);
        }
    };
    // Process the task queue during idle time
    EventCompressor.prototype.processQueue = function (idleDeadline) {
        var _this = this;
        // Process tasks while there's idle time or until the max number of tasks is reached
        while (this.taskQueue.length > 0 && (idleDeadline.timeRemaining() > 0 || idleDeadline.didTimeout)) {
            var task = this.taskQueue.shift();
            if (task) {
                var event_1 = task.event, sessionId = task.sessionId;
                this.addCompressedEvent(event_1, sessionId);
            }
        }
        // If there are still tasks in the queue, schedule the next idle callback
        if (this.taskQueue.length > 0) {
            requestIdleCallback(function (idleDeadline) {
                _this.processQueue(idleDeadline);
            }, { timeout: this.timeout });
        }
        else {
            this.isProcessing = false;
        }
    };
    return EventCompressor;
}());
exports.EventCompressor = EventCompressor;
//# sourceMappingURL=event-compressor.js.map