import { __decorate, __param } from '../../../../../external/tslib/tslib.es6.js';
import { localizeWithPath } from '../../nls.js';
import { ConfigurationScope, Extensions as Extensions$1 } from '../../platform/configuration/common/configurationRegistry.js';
import { Registry } from '../../platform/registry/common/platform.js';
import { WorkbenchState } from '../../platform/workspace/common/workspace.js';
import { IWorkspaceContextService } from '../../platform/workspace/common/workspace.service.js';
import { ConfigurationTarget } from '../../platform/configuration/common/configuration.js';
import { IConfigurationService } from '../../platform/configuration/common/configuration.service.js';
import { Disposable } from '../../base/common/lifecycle.js';
import { Emitter } from '../../base/common/event.js';
import { IRemoteAgentService } from '../services/remote/common/remoteAgentService.service.js';
import { isWindows, OperatingSystem } from '../../base/common/platform.js';
import { equals } from '../../base/common/objects.js';
import { DeferredPromise } from '../../base/common/async.js';
import { IUserDataProfilesService } from '../../platform/userDataProfile/common/userDataProfile.service.js';
const _moduleId = "vs/workbench/common/configuration";
const applicationConfigurationNodeBase = ( (Object.freeze({
    'id': 'application',
    'order': 100,
    'title': ( localizeWithPath(_moduleId, 0, "Application")),
    'type': 'object'
})));
const workbenchConfigurationNodeBase = ( (Object.freeze({
    'id': 'workbench',
    'order': 7,
    'title': ( localizeWithPath(_moduleId, 1, "Workbench")),
    'type': 'object',
})));
const securityConfigurationNodeBase = ( (Object.freeze({
    'id': 'security',
    'scope': ConfigurationScope.APPLICATION,
    'title': ( localizeWithPath(_moduleId, 2, "Security")),
    'type': 'object',
    'order': 7
})));
const problemsConfigurationNodeBase = ( (Object.freeze({
    'id': 'problems',
    'title': ( localizeWithPath(_moduleId, 3, "Problems")),
    'type': 'object',
    'order': 101
})));
const windowConfigurationNodeBase = ( (Object.freeze({
    'id': 'window',
    'order': 8,
    'title': ( localizeWithPath(_moduleId, 4, "Window")),
    'type': 'object',
})));
const Extensions = {
    ConfigurationMigration: 'base.contributions.configuration.migration'
};
class ConfigurationMigrationRegistry {
    constructor() {
        this.migrations = [];
        this._onDidRegisterConfigurationMigrations = ( (new Emitter()));
        this.onDidRegisterConfigurationMigration = this._onDidRegisterConfigurationMigrations.event;
    }
    registerConfigurationMigrations(configurationMigrations) {
        this.migrations.push(...configurationMigrations);
    }
}
const configurationMigrationRegistry = ( (new ConfigurationMigrationRegistry()));
Registry.add(Extensions.ConfigurationMigration, configurationMigrationRegistry);
let ConfigurationMigrationWorkbenchContribution = class ConfigurationMigrationWorkbenchContribution extends Disposable {
    static { this.ID = 'workbench.contrib.configurationMigration'; }
    constructor(configurationService, workspaceService) {
        super();
        this.configurationService = configurationService;
        this.workspaceService = workspaceService;
        this._register(this.workspaceService.onDidChangeWorkspaceFolders(async (e) => {
            for (const folder of e.added) {
                await this.migrateConfigurationsForFolder(folder, configurationMigrationRegistry.migrations);
            }
        }));
        this.migrateConfigurations(configurationMigrationRegistry.migrations);
        this._register(configurationMigrationRegistry.onDidRegisterConfigurationMigration(migration => this.migrateConfigurations(migration)));
    }
    async migrateConfigurations(migrations) {
        await this.migrateConfigurationsForFolder(undefined, migrations);
        for (const folder of this.workspaceService.getWorkspace().folders) {
            await this.migrateConfigurationsForFolder(folder, migrations);
        }
    }
    async migrateConfigurationsForFolder(folder, migrations) {
        await Promise.all([( (migrations.map(
            migration => this.migrateConfigurationsForFolderAndOverride(migration, folder?.uri)
        )))]);
    }
    async migrateConfigurationsForFolderAndOverride(migration, resource) {
        const inspectData = this.configurationService.inspect(migration.key, { resource });
        const targetPairs = this.workspaceService.getWorkbenchState() === WorkbenchState.WORKSPACE ? [
            ['user', ConfigurationTarget.USER],
            ['userLocal', ConfigurationTarget.USER_LOCAL],
            ['userRemote', ConfigurationTarget.USER_REMOTE],
            ['workspace', ConfigurationTarget.WORKSPACE],
            ['workspaceFolder', ConfigurationTarget.WORKSPACE_FOLDER],
        ] : [
            ['user', ConfigurationTarget.USER],
            ['userLocal', ConfigurationTarget.USER_LOCAL],
            ['userRemote', ConfigurationTarget.USER_REMOTE],
            ['workspace', ConfigurationTarget.WORKSPACE],
        ];
        for (const [dataKey, target] of targetPairs) {
            const inspectValue = inspectData[dataKey];
            if (!inspectValue) {
                continue;
            }
            const migrationValues = [];
            if (inspectValue.value !== undefined) {
                const keyValuePairs = await this.runMigration(migration, dataKey, inspectValue.value, resource, undefined);
                for (const keyValuePair of keyValuePairs ?? []) {
                    migrationValues.push([keyValuePair, []]);
                }
            }
            for (const { identifiers, value } of inspectValue.overrides ?? []) {
                if (value !== undefined) {
                    const keyValuePairs = await this.runMigration(migration, dataKey, value, resource, identifiers);
                    for (const keyValuePair of keyValuePairs ?? []) {
                        migrationValues.push([keyValuePair, identifiers]);
                    }
                }
            }
            if (migrationValues.length) {
                await Promise.allSettled(( (migrationValues.map(
                    async ([[key, value], overrideIdentifiers]) => this.configurationService.updateValue(key, value.value, { resource, overrideIdentifiers }, target)
                ))));
            }
        }
    }
    async runMigration(migration, dataKey, value, resource, overrideIdentifiers) {
        const valueAccessor = (key) => {
            const inspectData = this.configurationService.inspect(key, { resource });
            const inspectValue = inspectData[dataKey];
            if (!inspectValue) {
                return undefined;
            }
            if (!overrideIdentifiers) {
                return inspectValue.value;
            }
            return inspectValue.overrides?.find(({ identifiers }) => equals(identifiers, overrideIdentifiers))?.value;
        };
        const result = await migration.migrateFn(value, valueAccessor);
        return Array.isArray(result) ? result : [[migration.key, result]];
    }
};
ConfigurationMigrationWorkbenchContribution = ( (__decorate([
    ( (__param(0, IConfigurationService))),
    ( (__param(1, IWorkspaceContextService)))
], ConfigurationMigrationWorkbenchContribution)));
let DynamicWorkbenchSecurityConfiguration = class DynamicWorkbenchSecurityConfiguration extends Disposable {
    static { this.ID = 'workbench.contrib.dynamicWorkbenchSecurityConfiguration'; }
    constructor(remoteAgentService) {
        super();
        this.remoteAgentService = remoteAgentService;
        this._ready = ( (new DeferredPromise()));
        this.ready = this._ready.p;
        this.create();
    }
    async create() {
        try {
            await this.doCreate();
        }
        finally {
            this._ready.complete();
        }
    }
    async doCreate() {
        if (!isWindows) {
            const remoteEnvironment = await this.remoteAgentService.getEnvironment();
            if (remoteEnvironment?.os !== OperatingSystem.Windows) {
                return;
            }
        }
        const registry = ( (Registry.as(Extensions$1.Configuration)));
        registry.registerConfiguration({
            ...securityConfigurationNodeBase,
            'properties': {
                'security.allowedUNCHosts': {
                    'type': 'array',
                    'items': {
                        'type': 'string',
                        'pattern': '^[^\\\\]+$',
                        'patternErrorMessage': ( localizeWithPath(_moduleId, 5, 'UNC host names must not contain backslashes.'))
                    },
                    'default': [],
                    'markdownDescription': ( localizeWithPath(
                        _moduleId,
                        6,
                        'A set of UNC host names (without leading or trailing backslash, for example `192.168.0.1` or `my-server`) to allow without user confirmation. If a UNC host is being accessed that is not allowed via this setting or has not been acknowledged via user confirmation, an error will occur and the operation stopped. A restart is required when changing this setting. Find out more about this setting at https://aka.ms/vscode-windows-unc.'
                    )),
                    'scope': ConfigurationScope.MACHINE
                },
                'security.restrictUNCAccess': {
                    'type': 'boolean',
                    'default': true,
                    'markdownDescription': ( localizeWithPath(
                        _moduleId,
                        7,
                        'If enabled, only allows access to UNC host names that are allowed by the `#security.allowedUNCHosts#` setting or after user confirmation. Find out more about this setting at https://aka.ms/vscode-windows-unc.'
                    )),
                    'scope': ConfigurationScope.MACHINE
                }
            }
        });
    }
};
DynamicWorkbenchSecurityConfiguration = ( (__decorate([
    ( (__param(0, IRemoteAgentService)))
], DynamicWorkbenchSecurityConfiguration)));
const CONFIG_NEW_WINDOW_PROFILE = 'window.newWindowProfile';
let DynamicWindowConfiguration = class DynamicWindowConfiguration extends Disposable {
    static { this.ID = 'workbench.contrib.dynamicWindowConfiguration'; }
    constructor(userDataProfilesService, configurationService) {
        super();
        this.userDataProfilesService = userDataProfilesService;
        this.configurationService = configurationService;
        this.registerNewWindowProfileConfiguration();
        this._register(this.userDataProfilesService.onDidChangeProfiles((e) => this.registerNewWindowProfileConfiguration()));
        this.setNewWindowProfile();
        this.checkAndResetNewWindowProfileConfig();
        this._register(configurationService.onDidChangeConfiguration(e => {
            if (e.source !== ConfigurationTarget.DEFAULT && e.affectsConfiguration(CONFIG_NEW_WINDOW_PROFILE)) {
                this.setNewWindowProfile();
            }
        }));
        this._register(this.userDataProfilesService.onDidChangeProfiles(() => this.checkAndResetNewWindowProfileConfig()));
    }
    registerNewWindowProfileConfiguration() {
        const registry = ( (Registry.as(Extensions$1.Configuration)));
        const configurationNode = {
            ...windowConfigurationNodeBase,
            'properties': {
                [CONFIG_NEW_WINDOW_PROFILE]: {
                    'type': ['string', 'null'],
                    'default': null,
                    'enum': [...( (this.userDataProfilesService.profiles.map(profile => profile.name))), null],
                    'enumItemLabels': [...( (this.userDataProfilesService.profiles.map(p => ''))), ( localizeWithPath(_moduleId, 8, "Active Window"))],
                    'description': ( localizeWithPath(
                        _moduleId,
                        9,
                        "Specifies the profile to use when opening a new window. If a profile name is provided, the new window will use that profile. If no profile name is provided, the new window will use the profile of the active window or the default profile if no active window exists."
                    )),
                    'scope': ConfigurationScope.APPLICATION,
                }
            }
        };
        if (this.configurationNode) {
            registry.updateConfigurations({ add: [configurationNode], remove: [this.configurationNode] });
        }
        else {
            registry.registerConfiguration(configurationNode);
        }
        this.configurationNode = configurationNode;
    }
    setNewWindowProfile() {
        const newWindowProfileName = this.configurationService.getValue(CONFIG_NEW_WINDOW_PROFILE);
        this.newWindowProfile = newWindowProfileName ? this.userDataProfilesService.profiles.find(profile => profile.name === newWindowProfileName) : undefined;
    }
    checkAndResetNewWindowProfileConfig() {
        const newWindowProfileName = this.configurationService.getValue(CONFIG_NEW_WINDOW_PROFILE);
        if (!newWindowProfileName) {
            return;
        }
        const profile = this.newWindowProfile ? this.userDataProfilesService.profiles.find(profile => profile.id === this.newWindowProfile.id) : undefined;
        if (newWindowProfileName === profile?.name) {
            return;
        }
        this.configurationService.updateValue(CONFIG_NEW_WINDOW_PROFILE, profile?.name);
    }
};
DynamicWindowConfiguration = ( (__decorate([
    ( (__param(0, IUserDataProfilesService))),
    ( (__param(1, IConfigurationService)))
], DynamicWindowConfiguration)));
export { CONFIG_NEW_WINDOW_PROFILE, ConfigurationMigrationWorkbenchContribution, DynamicWindowConfiguration, DynamicWorkbenchSecurityConfiguration, Extensions, applicationConfigurationNodeBase, problemsConfigurationNodeBase, securityConfigurationNodeBase, windowConfigurationNodeBase, workbenchConfigurationNodeBase };
