import { __decorate, __param } from '../../../../../../../external/tslib/tslib.es6.js';
import { Emitter } from '../../../../base/common/event.js';
import { HierarchicalKind } from '../../../../base/common/hierarchicalKind.js';
import { Disposable } from '../../../../base/common/lifecycle.js';
import { editorConfigurationBaseNode } from '../../../../editor/common/config/editorConfigurationSchema.js';
import { ILanguageFeaturesService } from '../../../../editor/common/services/languageFeatures.js';
import { codeActionCommandId, refactorCommandId, sourceActionCommandId } from '../../../../editor/contrib/codeAction/browser/codeAction.js';
import { CodeActionKind } from '../../../../editor/contrib/codeAction/common/types.js';
import { localizeWithPath } from '../../../../nls.js';
import { ConfigurationScope, Extensions } from '../../../../platform/configuration/common/configurationRegistry.js';
import { IKeybindingService } from '../../../../platform/keybinding/common/keybinding.service.js';
import { Registry } from '../../../../platform/registry/common/platform.js';
const _moduleId = "vs/workbench/contrib/codeActions/browser/codeActionsContribution";
const createCodeActionsAutoSave = (description) => {
    return {
        type: 'string',
        enum: ['always', 'explicit', 'never', true, false],
        enumDescriptions: [
            ( localizeWithPath(
                _moduleId,
                0,
                'Triggers Code Actions on explicit saves and auto saves triggered by window or focus changes.'
            )),
            ( localizeWithPath(_moduleId, 1, 'Triggers Code Actions only when explicitly saved')),
            ( localizeWithPath(_moduleId, 2, 'Never triggers Code Actions on save')),
            ( localizeWithPath(
                _moduleId,
                3,
                'Triggers Code Actions only when explicitly saved. This value will be deprecated in favor of "explicit".'
            )),
            ( localizeWithPath(
                _moduleId,
                4,
                'Never triggers Code Actions on save. This value will be deprecated in favor of "never".'
            ))
        ],
        default: 'explicit',
        description: description
    };
};
const codeActionsOnSaveSchema = {
    oneOf: [
        {
            type: 'object',
            additionalProperties: {
                type: 'string'
            },
        },
        {
            type: 'array',
            items: { type: 'string' }
        }
    ],
    markdownDescription: ( localizeWithPath(
        _moduleId,
        5,
        'Run Code Actions for the editor on save. Code Actions must be specified and the editor must not be shutting down. Example: `"source.organizeImports": "explicit" `'
    )),
    type: ['object', 'array'],
    additionalProperties: {
        type: 'string',
        enum: ['always', 'explicit', 'never', true, false],
    },
    default: {},
    scope: ConfigurationScope.LANGUAGE_OVERRIDABLE,
};
const editorConfiguration = ( (Object.freeze({
    ...editorConfigurationBaseNode,
    properties: {
        'editor.codeActionsOnSave': codeActionsOnSaveSchema
    }
})));
let CodeActionsContribution = class CodeActionsContribution extends Disposable {
    constructor(codeActionsExtensionPoint, keybindingService, languageFeatures) {
        super();
        this.languageFeatures = languageFeatures;
        this._contributedCodeActions = [];
        this.settings = ( (new Set()));
        this._onDidChangeContributions = this._register(( (new Emitter())));
        languageFeatures.codeActionProvider.onDidChange(() => {
            this.updateSettingsFromCodeActionProviders();
            this.updateConfigurationSchemaFromContribs();
        }, 2000);
        codeActionsExtensionPoint.setHandler(extensionPoints => {
            this._contributedCodeActions = extensionPoints.flatMap(x => x.value).filter(x => Array.isArray(x.actions));
            this.updateConfigurationSchema(this._contributedCodeActions);
            this._onDidChangeContributions.fire();
        });
        keybindingService.registerSchemaContribution({
            getSchemaAdditions: () => this.getSchemaAdditions(),
            onDidChange: this._onDidChangeContributions.event,
        });
    }
    updateSettingsFromCodeActionProviders() {
        const providers = this.languageFeatures.codeActionProvider.allNoModel();
        providers.forEach(provider => {
            if (provider.providedCodeActionKinds) {
                provider.providedCodeActionKinds.forEach(kind => {
                    if (!( (this.settings.has(kind))) && CodeActionKind.Source.contains(( (new HierarchicalKind(kind))))) {
                        this.settings.add(kind);
                    }
                });
            }
        });
    }
    updateConfigurationSchema(codeActionContributions) {
        const newProperties = {};
        for (const [sourceAction, props] of this.getSourceActions(codeActionContributions)) {
            this.settings.add(sourceAction);
            newProperties[sourceAction] = createCodeActionsAutoSave(( localizeWithPath(
                _moduleId,
                6,
                "Controls whether '{0}' actions should be run on file save.",
                props.title
            )));
        }
        codeActionsOnSaveSchema.properties = newProperties;
        ( (Registry.as(Extensions.Configuration)))
            .notifyConfigurationSchemaUpdated(editorConfiguration);
    }
    updateConfigurationSchemaFromContribs() {
        const properties = { ...codeActionsOnSaveSchema.properties };
        for (const codeActionKind of this.settings) {
            if (!properties[codeActionKind]) {
                properties[codeActionKind] = createCodeActionsAutoSave(( localizeWithPath(
                    _moduleId,
                    6,
                    "Controls whether '{0}' actions should be run on file save.",
                    codeActionKind
                )));
            }
        }
        codeActionsOnSaveSchema.properties = properties;
        ( (Registry.as(Extensions.Configuration)))
            .notifyConfigurationSchemaUpdated(editorConfiguration);
    }
    getSourceActions(contributions) {
        const sourceActions = ( (new Map()));
        for (const contribution of contributions) {
            for (const action of contribution.actions) {
                const kind = ( (new HierarchicalKind(action.kind)));
                if (CodeActionKind.Source.contains(kind)) {
                    sourceActions.set(kind.value, action);
                }
            }
        }
        return sourceActions;
    }
    getSchemaAdditions() {
        const conditionalSchema = (command, actions) => {
            return {
                if: {
                    required: ['command'],
                    properties: {
                        'command': { const: command }
                    }
                },
                then: {
                    properties: {
                        'args': {
                            required: ['kind'],
                            properties: {
                                'kind': {
                                    anyOf: [
                                        {
                                            enum: ( (actions.map(action => action.kind))),
                                            enumDescriptions: ( (actions.map(action => action.description ?? action.title))),
                                        },
                                        { type: 'string' },
                                    ]
                                }
                            }
                        }
                    }
                }
            };
        };
        const getActions = (ofKind) => {
            const allActions = this._contributedCodeActions.flatMap(desc => desc.actions);
            const out = ( (new Map()));
            for (const action of allActions) {
                if (!( (out.has(action.kind))) && ofKind.contains(( (new HierarchicalKind(action.kind))))) {
                    out.set(action.kind, action);
                }
            }
            return Array.from(( (out.values())));
        };
        return [
            conditionalSchema(codeActionCommandId, getActions(HierarchicalKind.Empty)),
            conditionalSchema(refactorCommandId, getActions(CodeActionKind.Refactor)),
            conditionalSchema(sourceActionCommandId, getActions(CodeActionKind.Source)),
        ];
    }
};
CodeActionsContribution = ( (__decorate([
    ( (__param(1, IKeybindingService))),
    ( (__param(2, ILanguageFeaturesService)))
], CodeActionsContribution)));
export { CodeActionsContribution, editorConfiguration };
