const core = require('@sentry/core');
const utils = require('@sentry/utils');
const electron = require('electron');
const context = require('../context.js');
const electronNormalize = require('../electron-normalize.js');
const normalize = require('../../common/normalize.js');

const DOCUMENT_POLICY_HEADER = 'Document-Policy';
const JS_PROFILING_HEADER = 'js-profiling';
// A cache of renderer profiles which need attaching to events
let RENDERER_PROFILES;
/**
 * Caches a profile to later be re-attached to an event
 */
function rendererProfileFromIpc(event, profile) {
    if (!RENDERER_PROFILES) {
        return;
    }
    const profile_id = profile.event_id;
    RENDERER_PROFILES.set(profile_id, profile);
    if (event) {
        event.contexts = Object.assign(Object.assign({}, event.contexts), { 
            // Re-add the profile context which we can later use to find the correct profile
            profile: {
                profile_id,
            } });
    }
}
function addJsProfilingHeader(responseHeaders = {}) {
    if (responseHeaders[DOCUMENT_POLICY_HEADER]) {
        const docPolicy = responseHeaders[DOCUMENT_POLICY_HEADER];
        if (Array.isArray(docPolicy)) {
            docPolicy.push(JS_PROFILING_HEADER);
        }
        else {
            responseHeaders[DOCUMENT_POLICY_HEADER] = [docPolicy, JS_PROFILING_HEADER];
        }
    }
    else {
        responseHeaders[DOCUMENT_POLICY_HEADER] = JS_PROFILING_HEADER;
    }
    return { responseHeaders };
}
const INTEGRATION_NAME = 'RendererProfiling';
/**
 * Injects 'js-profiling' document policy headers and ensures that profiles get forwarded with transactions
 */
const rendererProfilingIntegration = core.defineIntegration(() => {
    return {
        name: INTEGRATION_NAME,
        setupOnce() {
            // noop
        },
        setup(client) {
            var _a;
            const options = client.getOptions();
            if (!options.enableRendererProfiling) {
                return;
            }
            if (electronNormalize.ELECTRON_MAJOR_VERSION < 15) {
                throw new Error('Renderer profiling requires Electron 15+ (Chromium 94+)');
            }
            RENDERER_PROFILES = new utils.LRUMap(10);
            electron.app.on('ready', () => {
                // Ensure the correct headers are set to enable the browser profiler
                for (const sesh of options.getSessions()) {
                    sesh.webRequest.onHeadersReceived((details, callback) => {
                        callback(addJsProfilingHeader(details.responseHeaders));
                    });
                }
            });
            // Copy the profiles back into the event envelopes
            (_a = client.on) === null || _a === void 0 ? void 0 : _a.call(client, 'beforeEnvelope', (envelope) => {
                let profile_id;
                utils.forEachEnvelopeItem(envelope, (item, type) => {
                    var _a, _b;
                    if (type !== 'transaction') {
                        return;
                    }
                    for (let j = 1; j < item.length; j++) {
                        const event = item[j];
                        if ((_b = (_a = event === null || event === void 0 ? void 0 : event.contexts) === null || _a === void 0 ? void 0 : _a.profile) === null || _b === void 0 ? void 0 : _b.profile_id) {
                            profile_id = event.contexts.profile.profile_id;
                            // This can be removed as it's no longer needed
                            delete event.contexts.profile;
                        }
                    }
                });
                if (!profile_id) {
                    return;
                }
                const profile = RENDERER_PROFILES === null || RENDERER_PROFILES === void 0 ? void 0 : RENDERER_PROFILES.remove(profile_id);
                if (!profile) {
                    return;
                }
                normalize.normaliseProfile(profile, electron.app.getAppPath());
                profile.release = options.release || context.getDefaultReleaseName();
                profile.environment = options.environment || context.getDefaultEnvironment();
                // @ts-expect-error untyped envelope
                envelope[1].push([{ type: 'profile' }, profile]);
            });
        },
    };
});
/**
 * Injects 'js-profiling' document policy headers and ensures that profiles get forwarded with transactions
 *
 * @deprecated Use `rendererProfilingIntegration()` instead
 */
// eslint-disable-next-line deprecation/deprecation
const RendererProfiling = core.convertIntegrationFnToClass(INTEGRATION_NAME, rendererProfilingIntegration);

exports.RendererProfiling = RendererProfiling;
exports.rendererProfileFromIpc = rendererProfileFromIpc;
exports.rendererProfilingIntegration = rendererProfilingIntegration;
//# sourceMappingURL=renderer-profiling.js.map
