const tslib = require('tslib');
const utils = require('@sentry/utils');
const electron = require('electron');
const path = require('path');
const ipc = require('../common/ipc.js');

const parsed = utils.parseSemver(process.versions.electron);
const version = { major: parsed.major || 0, minor: parsed.minor || 0, patch: parsed.patch || 0 };
const ELECTRON_MAJOR_VERSION = version.major;
/** Returns if the app is packaged. Copied from Electron to support < v3 */
const isPackaged = (() => {
    const execFile = path.basename(process.execPath).toLowerCase();
    if (process.platform === 'win32') {
        return execFile !== 'electron.exe';
    }
    return execFile !== 'electron';
})();
/** A promise that is resolved when the app is ready */
const whenAppReady = (() => {
    if (electron.app) {
        return electron.app.isReady()
            ? Promise.resolve()
            : new Promise((resolve) => {
                electron.app.once('ready', () => {
                    resolve();
                });
            });
    }
    return Promise.resolve();
})();
/**
 * Electron >= 5 support full protocol API
 */
function supportsFullProtocol() {
    return version.major >= 5;
}
const EXIT_REASONS = [
    'clean-exit',
    'abnormal-exit',
    'killed',
    'crashed',
    'oom',
    'launch-failed',
    'integrity-failure',
];
const CRASH_REASONS = ['crashed', 'oom'];
/**
 * Implements 'render-process-gone' event across Electron versions
 */
function onRendererProcessGone(reasons, callback) {
    const supportsRenderProcessGone = version.major >= 10 || (version.major === 9 && version.minor >= 1) || (version.major === 8 && version.minor >= 4);
    if (supportsRenderProcessGone) {
        electron.app.on('render-process-gone', (_, contents, details) => {
            if (reasons.includes(details.reason)) {
                callback(contents, details);
            }
        });
    }
    else {
        onWebContentsCreated((contents) => {
            // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
            contents.on('crashed', (__, killed) => {
                // When using Breakpad, crashes are incorrectly reported as killed
                const reason = usesCrashpad() && killed ? 'killed' : 'crashed';
                if (reasons.includes(reason)) {
                    callback(contents, { reason });
                }
            });
        });
    }
}
/**
 * Calls callback on child process crash if Electron version support 'child-process-gone' event
 */
function onChildProcessGone(reasons, callback) {
    if (version.major >= 11) {
        electron.app.on('child-process-gone', (_, details) => {
            if (reasons.includes(details.reason)) {
                callback(details);
            }
        });
    }
    else {
        // eslint-disable-next-line deprecation/deprecation
        electron.app.on('gpu-process-crashed', (_, killed) => {
            const reason = killed ? 'killed' : 'crashed';
            if (reasons.includes(reason)) {
                callback({ type: 'GPU', reason });
            }
        });
    }
}
/** Calls callback when BrowserWindow are created */
function onBrowserWindowCreated(callback) {
    electron.app.on('browser-window-created', (_, window) => {
        // SetImmediate is required for window.id to be correct in older versions of Electron
        // https://github.com/electron/electron/issues/12036
        if (version.major >= 3) {
            callback(window);
        }
        else {
            setImmediate(() => {
                if (window.isDestroyed()) {
                    return;
                }
                callback(window);
            });
        }
    });
}
/** Calls callback when WebContents are created */
function onWebContentsCreated(callback) {
    electron.app.on('web-contents-created', (_, contents) => {
        // SetImmediate is required for contents.id to be correct in older versions of Electron
        // https://github.com/electron/electron/issues/12036
        if (version.major >= 3) {
            callback(contents);
        }
        else {
            setImmediate(() => {
                if (contents.isDestroyed()) {
                    return;
                }
                callback(contents);
            });
        }
    });
}
/**
 * Electron < 9 requires `crashReporter.start()` in the renderer
 */
function rendererRequiresCrashReporterStart() {
    if (process.platform === 'darwin') {
        return false;
    }
    return version.major < 9;
}
/**
 * Uses Crashpad on Linux
 * https://github.com/electron/electron/issues/27859
 */
function crashpadLinux() {
    if (version.major >= 16) {
        return true;
    }
    if (version.major < 15) {
        return false;
    }
    // Crashpad Linux for v15 is behind a switch
    return electron.app.commandLine.hasSwitch('enable-crashpad');
}
/** Is using Crashpad */
function usesCrashpad() {
    return (process.platform === 'darwin' ||
        (process.platform === 'win32' && version.major >= 6) ||
        (process.platform === 'linux' && crashpadLinux()));
}
/**
 * Electron >= 9 uses `app.getPath('crashDumps')` rather than
 * `crashReporter.getCrashesDirectory()`
 */
function getCrashesDirectory() {
    return version.major >= 9
        ? electron.app.getPath('crashDumps')
        : // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
            electron.crashReporter.getCrashesDirectory();
}
/** Captures a NativeImage from a BrowserWindow */
function capturePage(window) {
    // Pre-Electron 5, BrowserWindow.capturePage() uses callbacks
    if (version.major < 5) {
        return new Promise((resolve) => {
            window.capturePage(resolve);
        });
    }
    return window.capturePage();
}
/**
 * Electron >= 25 support `protocol.handle`
 */
function supportsProtocolHandle() {
    return version.major >= 25;
}
/**
 * Registers a custom protocol to receive events from the renderer
 *
 * Uses `protocol.handle` if available, otherwise falls back to `protocol.registerStringProtocol`
 */
function registerProtocol(protocol, scheme, callback) {
    if (supportsProtocolHandle()) {
        protocol.handle(scheme, (request) => tslib.__awaiter(this, void 0, void 0, function* () {
            callback({
                windowId: request.headers.get(ipc.RENDERER_ID_HEADER) || undefined,
                url: request.url,
                body: Buffer.from(yield request.arrayBuffer()),
            });
            return new Response('');
        }));
    }
    else {
        // eslint-disable-next-line deprecation/deprecation
        protocol.registerStringProtocol(scheme, (request, complete) => {
            var _a, _b;
            callback({
                windowId: request.headers[ipc.RENDERER_ID_HEADER],
                url: request.url,
                body: (_b = (_a = request.uploadData) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.bytes,
            });
            complete('');
        });
    }
}

exports.CRASH_REASONS = CRASH_REASONS;
exports.ELECTRON_MAJOR_VERSION = ELECTRON_MAJOR_VERSION;
exports.EXIT_REASONS = EXIT_REASONS;
exports.capturePage = capturePage;
exports.getCrashesDirectory = getCrashesDirectory;
exports.isPackaged = isPackaged;
exports.onBrowserWindowCreated = onBrowserWindowCreated;
exports.onChildProcessGone = onChildProcessGone;
exports.onRendererProcessGone = onRendererProcessGone;
exports.onWebContentsCreated = onWebContentsCreated;
exports.registerProtocol = registerProtocol;
exports.rendererRequiresCrashReporterStart = rendererRequiresCrashReporterStart;
exports.supportsFullProtocol = supportsFullProtocol;
exports.usesCrashpad = usesCrashpad;
exports.whenAppReady = whenAppReady;
//# sourceMappingURL=electron-normalize.js.map
