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 { 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 { Extensions } from '../../../../platform/configuration/common/configurationRegistry.js';
import { IKeybindingService } from '../../../../platform/keybinding/common/keybinding.js';
import { Registry } from '../../../../platform/registry/common/platform.js';
const createCodeActionsAutoSave = (description) => {
    return {
        type: 'string',
        enum: ['always', 'explicit', 'never', true, false],
        enumDescriptions: [
            ( localizeWithPath(
                'vs/workbench/contrib/codeActions/browser/codeActionsContribution',
                'alwaysSave',
                'Triggers Code Actions on explicit saves and auto saves triggered by window or focus changes.'
            )),
            ( localizeWithPath(
                'vs/workbench/contrib/codeActions/browser/codeActionsContribution',
                'explicitSave',
                'Triggers Code Actions only when explicitly saved'
            )),
            ( localizeWithPath(
                'vs/workbench/contrib/codeActions/browser/codeActionsContribution',
                'neverSave',
                'Never triggers Code Actions on save'
            )),
            ( localizeWithPath(
                'vs/workbench/contrib/codeActions/browser/codeActionsContribution',
                'explicitSaveBoolean',
                'Triggers Code Actions only when explicitly saved. This value will be deprecated in favor of "explicit".'
            )),
            ( localizeWithPath(
                'vs/workbench/contrib/codeActions/browser/codeActionsContribution',
                'neverSaveBoolean',
                'Never triggers Code Actions on save. This value will be deprecated in favor of "never".'
            ))
        ],
        default: 'explicit',
        description: description
    };
};
const codeActionsOnSaveDefaultProperties = ( Object.freeze({
    'source.fixAll': createCodeActionsAutoSave(( localizeWithPath(
        'vs/workbench/contrib/codeActions/browser/codeActionsContribution',
        'codeActionsOnSave.fixAll',
        "Controls whether auto fix action should be run on file save."
    ))),
}));
const codeActionsOnSaveSchema = {
    oneOf: [
        {
            type: 'object',
            properties: codeActionsOnSaveDefaultProperties,
            additionalProperties: {
                type: 'string'
            },
        },
        {
            type: 'array',
            items: { type: 'string' }
        }
    ],
    markdownDescription: ( localizeWithPath(
        'vs/workbench/contrib/codeActions/browser/codeActionsContribution',
        'editor.codeActionsOnSave',
        '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: 5 ,
};
const editorConfiguration = ( Object.freeze({
    ...editorConfigurationBaseNode,
    properties: {
        'editor.codeActionsOnSave': codeActionsOnSaveSchema
    }
}));
let CodeActionsContribution = class CodeActionsContribution extends Disposable {
    constructor(codeActionsExtensionPoint, keybindingService) {
        super();
        this._contributedCodeActions = [];
        this._onDidChangeContributions = this._register(( new Emitter()));
        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,
        });
    }
    updateConfigurationSchema(codeActionContributions) {
        const newProperties = { ...codeActionsOnSaveDefaultProperties };
        for (const [sourceAction, props] of this.getSourceActions(codeActionContributions)) {
            newProperties[sourceAction] = createCodeActionsAutoSave(( localizeWithPath(
                'vs/workbench/contrib/codeActions/browser/codeActionsContribution',
                'codeActionsOnSave.generic',
                "Controls whether '{0}' actions should be run on file save.",
                props.title
            )));
        }
        codeActionsOnSaveSchema.properties = newProperties;
        ( Registry.as(Extensions.Configuration))
            .notifyConfigurationSchemaUpdated(editorConfiguration);
    }
    getSourceActions(contributions) {
        const defaultKinds = ( ( Object.keys(codeActionsOnSaveDefaultProperties)).map(value => ( new HierarchicalKind(value))));
        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)
                    && !( defaultKinds.some(defaultKind => defaultKind.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))
], CodeActionsContribution));
export { CodeActionsContribution, editorConfiguration };
