const core = require('@sentry/core');
const node = require('@sentry/node');
const electron = require('electron');
const urlModule = require('url');

function _interopNamespaceDefault(e) {
    const n = Object.create(null);
    if (e) {
        for (const k in e) {
            n[k] = e[k];
        }
    }
    n.default = e;
    return n;
}

const urlModule__namespace = /*#__PURE__*/_interopNamespaceDefault(urlModule);

/**
 * Trimmed down version of the code from Electron here:
 * https://github.com/electron/electron/blob/f3df76dbdc58cb704637b89357e1400791c92cfe/lib/browser/api/net.ts#L209-L269
 *
 * We want to match the final URL that Electron uses
 */
function parseOptions(optionsIn) {
    const { method, options } = typeof optionsIn === 'string'
        ? // eslint-disable-next-line deprecation/deprecation
            { method: 'GET', options: urlModule__namespace.parse(optionsIn) }
        : { method: (optionsIn.method || 'GET').toUpperCase(), options: optionsIn };
    let url = 'url' in options ? options.url : undefined;
    if (!url) {
        const urlObj = {};
        urlObj.protocol = options.protocol || 'http:';
        if (options.host) {
            urlObj.host = options.host;
        }
        else {
            if (options.hostname) {
                urlObj.hostname = options.hostname;
            }
            else {
                urlObj.hostname = 'localhost';
            }
            if (options.port) {
                urlObj.port = options.port;
            }
        }
        // eslint-disable-next-line deprecation/deprecation
        const pathObj = urlModule__namespace.parse(options.path || '/');
        urlObj.pathname = pathObj.pathname;
        urlObj.search = pathObj.search;
        urlObj.hash = pathObj.hash;
        url = urlModule__namespace.format(urlObj);
    }
    return {
        method,
        url,
    };
}
function createWrappedRequestFactory(options, enableLogs, tracePropagationTargets) {
    // We're caching results so we don't have to recompute regexp every time we create a request.
    const createSpanUrlMap = new core.LRUMap(100);
    const headersUrlMap = new core.LRUMap(100);
    const shouldCreateSpan = (method, url) => {
        if (options.tracing === undefined) {
            return true;
        }
        if (options.tracing === false) {
            return false;
        }
        const key = `${method}:${url}`;
        const cachedDecision = createSpanUrlMap.get(key);
        if (cachedDecision !== undefined) {
            return cachedDecision;
        }
        const decision = options.tracing === true || options.tracing(method, url);
        createSpanUrlMap.set(key, decision);
        return decision;
    };
    // This will be considerably simpler once `tracingOrigins` is removed in the next major release
    const shouldAttachTraceData = (method, url) => {
        const key = `${method}:${url}`;
        const cachedDecision = headersUrlMap.get(key);
        if (cachedDecision !== undefined) {
            return cachedDecision;
        }
        if (tracePropagationTargets) {
            const decision = core.stringMatchesSomePattern(url, tracePropagationTargets);
            headersUrlMap.set(key, decision);
            return decision;
        }
        // We cannot reach here since either `tracePropagationTargets` or `tracingOrigins` will be defined but TypeScript
        // cannot infer that
        return true;
    };
    /**
     * Captures Breadcrumb based on provided request/response pair
     */
    const addRequestBreadcrumb = (event, method, url, req, res) => {
        const level = core.getBreadcrumbLogLevelFromHttpStatusCode(res?.statusCode);
        core.addBreadcrumb({
            type: 'http',
            category: 'electron.net',
            data: {
                url,
                method: method,
                status_code: res?.statusCode,
            },
            level,
        }, {
            event,
            request: req,
            response: res,
        });
        if (!enableLogs) {
            return;
        }
        const attributes = {
            'sentry.origin': 'auto.electron.net',
            statusCode: res?.statusCode,
        };
        switch (level) {
            case 'error':
                node.logger.error(node.logger.fmt `Electron.net request failed: ${method} ${url}`, attributes);
                break;
            case 'warning':
                node.logger.warn(node.logger.fmt `Electron.net request warning: ${method} ${url}`, attributes);
                break;
            default:
                node.logger.info(node.logger.fmt `Electron.net request succeeded: ${method} ${url}`, attributes);
        }
    };
    return function wrappedRequestMethodFactory(originalRequestMethod) {
        return function requestMethod(reqOptions) {
            const { url, method } = parseOptions(reqOptions);
            const request = originalRequestMethod.apply(this, [reqOptions]);
            if (url.match(/sentry_key/) || request.getHeader('x-sentry-auth')) {
                return request;
            }
            const span = shouldCreateSpan(method, url)
                ? core.startInactiveSpan({
                    name: `${method} ${url}`,
                    onlyIfParent: true,
                    attributes: {
                        url,
                        type: 'net.request',
                        'http.method': method,
                    },
                    op: 'http.client',
                })
                : new core.SentryNonRecordingSpan();
            span.setAttribute(core.SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, 'auto.http.electron.net');
            if (shouldAttachTraceData(method, url)) {
                for (const [key, value] of Object.entries(core.getTraceData({ span }))) {
                    core.debug.log(`[Tracing] Adding ${key} header ${value} to outgoing request to "${url}": `);
                    request.setHeader(key, value);
                }
            }
            return request
                .once('response', function (res) {
                if (options.breadcrumbs !== false) {
                    addRequestBreadcrumb('response', method, url, this, res);
                }
                if (res.statusCode) {
                    core.setHttpStatus(span, res.statusCode);
                }
                span.end();
            })
                .once('error', function (_error) {
                if (options.breadcrumbs !== false) {
                    addRequestBreadcrumb('error', method, url, this, undefined);
                }
                core.setHttpStatus(span, 500);
                span.end();
            });
        };
    };
}
/**
 * Electron 'net' module integration
 */
const electronNetIntegration = core.defineIntegration((options = {}) => {
    return {
        name: 'ElectronNet',
        setup(client) {
            const clientOptions = client.getOptions();
            const enableLogs = !!clientOptions?.enableLogs;
            // No need to instrument if we don't want to track anything
            if (options.breadcrumbs === false && options.tracing === false) {
                return;
            }
            core.fill(electron.net, 'request', createWrappedRequestFactory(options, enableLogs, clientOptions?.tracePropagationTargets));
        },
    };
});

exports.electronNetIntegration = electronNetIntegration;//# sourceMappingURL=http://go/sourcemap/sourcemaps/31e8d61c448c7472e371505838a0fe34083dad50/node_modules/@sentry/electron/main/integrations/net-breadcrumbs.js.map
