import { cloneAndChange } from '../../../base/common/objects.js';
import { getRemoteName } from '../../remote/common/remoteHosts.js';
import '../../../base/common/platform.js';
import '../../../base/common/process.js';
import { TELEMETRY_SETTING_ID, TELEMETRY_CRASH_REPORTER_SETTING_ID, TELEMETRY_OLD_SETTING_ID } from './telemetry.js';
class TelemetryTrustedValue {
    constructor(value) {
        this.value = value;
        this.isTrustedTelemetryValue = true;
    }
}
class NullEndpointTelemetryService {
    async publicLog(_endpoint, _eventName, _data) {
    }
    async publicLogError(_endpoint, _errorEventName, _data) {
    }
}
const telemetryLogId = 'telemetry';
const extensionTelemetryLogChannelId = 'extensionTelemetryLog';
function supportsTelemetry(productService, environmentService) {
    if (!environmentService.isBuilt && !environmentService.disableTelemetry) {
        return true;
    }
    return !(environmentService.disableTelemetry || !productService.enableTelemetry);
}
function isLoggingOnly(productService, environmentService) {
    if (environmentService.extensionTestsLocationURI) {
        return true;
    }
    if (environmentService.isBuilt) {
        return false;
    }
    if (environmentService.disableTelemetry) {
        return false;
    }
    if (productService.enableTelemetry && productService.aiConfig?.ariaKey) {
        return false;
    }
    return true;
}
function getTelemetryLevel(configurationService) {
    const newConfig = configurationService.getValue(TELEMETRY_SETTING_ID);
    const crashReporterConfig = configurationService.getValue(TELEMETRY_CRASH_REPORTER_SETTING_ID);
    const oldConfig = configurationService.getValue(TELEMETRY_OLD_SETTING_ID);
    if (oldConfig === false || crashReporterConfig === false) {
        return 0 ;
    }
    switch (newConfig ?? "all" ) {
        case "all" :
            return 3 ;
        case "error" :
            return 2 ;
        case "crash" :
            return 1 ;
        case "off" :
            return 0 ;
    }
}
const telemetryAllowedAuthorities = ( new Set(
    ['ssh-remote', 'dev-container', 'attached-container', 'wsl', 'tunnel', 'codespaces', 'amlext']
));
function cleanRemoteAuthority(remoteAuthority) {
    if (!remoteAuthority) {
        return 'none';
    }
    const remoteName = getRemoteName(remoteAuthority);
    return ( telemetryAllowedAuthorities.has(remoteName)) ? remoteName : 'other';
}
function anonymizeFilePaths(stack, cleanupPatterns) {
    if (!stack || (!stack.includes('/') && !stack.includes('\\'))) {
        return stack;
    }
    let updatedStack = stack;
    const cleanUpIndexes = [];
    for (const regexp of cleanupPatterns) {
        while (true) {
            const result = regexp.exec(stack);
            if (!result) {
                break;
            }
            cleanUpIndexes.push([result.index, regexp.lastIndex]);
        }
    }
    const nodeModulesRegex = /^[\\\/]?(node_modules|node_modules\.asar)[\\\/]/;
    const fileRegex = /(file:\/\/)?([a-zA-Z]:(\\\\|\\|\/)|(\\\\|\\|\/))?([\w-\._]+(\\\\|\\|\/))+[\w-\._]*/g;
    let lastIndex = 0;
    updatedStack = '';
    while (true) {
        const result = fileRegex.exec(stack);
        if (!result) {
            break;
        }
        const overlappingRange = ( cleanUpIndexes.some(([start, end]) => result.index < end && start < fileRegex.lastIndex));
        if (!nodeModulesRegex.test(result[0]) && !overlappingRange) {
            updatedStack += stack.substring(lastIndex, result.index) + '<REDACTED: user-file-path>';
            lastIndex = fileRegex.lastIndex;
        }
    }
    if (lastIndex < stack.length) {
        updatedStack += stack.substr(lastIndex);
    }
    return updatedStack;
}
function removePropertiesWithPossibleUserInfo(property) {
    if (!property) {
        return property;
    }
    const userDataRegexes = [
        { label: 'Google API Key', regex: /AIza[A-Za-z0-9_\\\-]{35}/ },
        { label: 'Slack Token', regex: /xox[pbar]\-[A-Za-z0-9]/ },
        { label: 'GitHub Token', regex: /(gh[psuro]_[a-zA-Z0-9]{36}|github_pat_[a-zA-Z0-9]{22}_[a-zA-Z0-9]{59})/ },
        { label: 'Generic Secret', regex: /(key|token|sig|secret|signature|password|passwd|pwd|android:value)[^a-zA-Z0-9]/i },
        { label: 'Email', regex: /@[a-zA-Z0-9-]+\.[a-zA-Z0-9-]+/ }
    ];
    for (const secretRegex of userDataRegexes) {
        if (secretRegex.regex.test(property)) {
            return `<REDACTED: ${secretRegex.label}>`;
        }
    }
    return property;
}
function cleanData(data, cleanUpPatterns) {
    return cloneAndChange(data, value => {
        if (value instanceof TelemetryTrustedValue || Object.hasOwnProperty.call(value, 'isTrustedTelemetryValue')) {
            return value.value;
        }
        if (typeof value === 'string') {
            let updatedProperty = value.replaceAll('%20', ' ');
            updatedProperty = anonymizeFilePaths(updatedProperty, cleanUpPatterns);
            for (const regexp of cleanUpPatterns) {
                updatedProperty = updatedProperty.replace(regexp, '');
            }
            updatedProperty = removePropertiesWithPossibleUserInfo(updatedProperty);
            return updatedProperty;
        }
        return undefined;
    });
}
export { NullEndpointTelemetryService, TelemetryTrustedValue, cleanData, cleanRemoteAuthority, extensionTelemetryLogChannelId, getTelemetryLevel, isLoggingOnly, supportsTelemetry, telemetryLogId };
