import { HierarchicalKind } from '../../../../base/common/hierarchicalKind.js';
import { escapeRegExpCharacters } from '../../../../base/common/strings.js';
import { EditorCommand, EditorAction } from '../../../browser/editorExtensions.js';
import { EditorContextKeys } from '../../../common/editorContextKeys.js';
import { codeActionCommandId, quickFixCommandId, refactorCommandId, sourceActionCommandId, organizeImportsCommandId, fixAllCommandId, autoFixCommandId } from './codeAction.js';
import { localizeWithPath } from '../../../../nls.js';
import { ContextKeyExpr } from '../../../../platform/contextkey/common/contextkey.js';
import { CodeActionCommandArgs, CodeActionTriggerSource, CodeActionKind } from '../common/types.js';
import { CodeActionController } from './codeActionController.js';
import { SUPPORTED_CODE_ACTIONS } from './codeActionModel.js';
function contextKeyForSupportedActions(kind) {
    return ( ContextKeyExpr.regex(( SUPPORTED_CODE_ACTIONS.keys())[0], ( new RegExp('(\\s|^)' + escapeRegExpCharacters(kind.value) + '\\b'))));
}
const argsSchema = {
    type: 'object',
    defaultSnippets: [{ body: { kind: '' } }],
    properties: {
        'kind': {
            type: 'string',
            description: ( localizeWithPath(
                'vs/editor/contrib/codeAction/browser/codeActionCommands',
                'args.schema.kind',
                "Kind of the code action to run."
            )),
        },
        'apply': {
            type: 'string',
            description: ( localizeWithPath(
                'vs/editor/contrib/codeAction/browser/codeActionCommands',
                'args.schema.apply',
                "Controls when the returned actions are applied."
            )),
            default: "ifSingle" ,
            enum: ["first" , "ifSingle" , "never" ],
            enumDescriptions: [
                ( localizeWithPath(
                    'vs/editor/contrib/codeAction/browser/codeActionCommands',
                    'args.schema.apply.first',
                    "Always apply the first returned code action."
                )),
                ( localizeWithPath(
                    'vs/editor/contrib/codeAction/browser/codeActionCommands',
                    'args.schema.apply.ifSingle',
                    "Apply the first returned code action if it is the only one."
                )),
                ( localizeWithPath(
                    'vs/editor/contrib/codeAction/browser/codeActionCommands',
                    'args.schema.apply.never',
                    "Do not apply the returned code actions."
                )),
            ]
        },
        'preferred': {
            type: 'boolean',
            default: false,
            description: ( localizeWithPath(
                'vs/editor/contrib/codeAction/browser/codeActionCommands',
                'args.schema.preferred',
                "Controls if only preferred code actions should be returned."
            )),
        }
    }
};
function triggerCodeActionsForEditorSelection(editor, notAvailableMessage, filter, autoApply, triggerAction = CodeActionTriggerSource.Default) {
    if (editor.hasModel()) {
        const controller = CodeActionController.get(editor);
        controller?.manualTriggerAtCurrentPosition(notAvailableMessage, triggerAction, filter, autoApply);
    }
}
class QuickFixAction extends EditorAction {
    constructor() {
        super({
            id: quickFixCommandId,
            label: ( localizeWithPath(
                'vs/editor/contrib/codeAction/browser/codeActionCommands',
                'quickfix.trigger.label',
                "Quick Fix..."
            )),
            alias: 'Quick Fix...',
            precondition: ( ContextKeyExpr.and(EditorContextKeys.writable, EditorContextKeys.hasCodeActionsProvider)),
            kbOpts: {
                kbExpr: EditorContextKeys.textInputFocus,
                primary: 2048  | 89 ,
                weight: 100
            }
        });
    }
    run(_accessor, editor) {
        return triggerCodeActionsForEditorSelection(editor, ( localizeWithPath(
            'vs/editor/contrib/codeAction/browser/codeActionCommands',
            'editor.action.quickFix.noneMessage',
            "No code actions available"
        )), undefined, undefined, CodeActionTriggerSource.QuickFix);
    }
}
class CodeActionCommand extends EditorCommand {
    constructor() {
        super({
            id: codeActionCommandId,
            precondition: ( ContextKeyExpr.and(EditorContextKeys.writable, EditorContextKeys.hasCodeActionsProvider)),
            metadata: {
                description: 'Trigger a code action',
                args: [{ name: 'args', schema: argsSchema, }]
            }
        });
    }
    runEditorCommand(_accessor, editor, userArgs) {
        const args = CodeActionCommandArgs.fromUser(userArgs, {
            kind: HierarchicalKind.Empty,
            apply: "ifSingle" ,
        });
        return triggerCodeActionsForEditorSelection(editor, typeof userArgs?.kind === 'string'
            ? args.preferred
                ? ( localizeWithPath(
            'vs/editor/contrib/codeAction/browser/codeActionCommands',
            'editor.action.codeAction.noneMessage.preferred.kind',
            "No preferred code actions for '{0}' available",
            userArgs.kind
        ))
                : ( localizeWithPath(
            'vs/editor/contrib/codeAction/browser/codeActionCommands',
            'editor.action.codeAction.noneMessage.kind',
            "No code actions for '{0}' available",
            userArgs.kind
        ))
            : args.preferred
                ? ( localizeWithPath(
            'vs/editor/contrib/codeAction/browser/codeActionCommands',
            'editor.action.codeAction.noneMessage.preferred',
            "No preferred code actions available"
        ))
                : ( localizeWithPath(
            'vs/editor/contrib/codeAction/browser/codeActionCommands',
            'editor.action.codeAction.noneMessage',
            "No code actions available"
        )), {
            include: args.kind,
            includeSourceActions: true,
            onlyIncludePreferredActions: args.preferred,
        }, args.apply);
    }
}
class RefactorAction extends EditorAction {
    constructor() {
        super({
            id: refactorCommandId,
            label: ( localizeWithPath(
                'vs/editor/contrib/codeAction/browser/codeActionCommands',
                'refactor.label',
                "Refactor..."
            )),
            alias: 'Refactor...',
            precondition: ( ContextKeyExpr.and(EditorContextKeys.writable, EditorContextKeys.hasCodeActionsProvider)),
            kbOpts: {
                kbExpr: EditorContextKeys.textInputFocus,
                primary: 2048  | 1024  | 48 ,
                mac: {
                    primary: 256  | 1024  | 48
                },
                weight: 100
            },
            contextMenuOpts: {
                group: '1_modification',
                order: 2,
                when: ( ContextKeyExpr.and(
                    EditorContextKeys.writable,
                    contextKeyForSupportedActions(CodeActionKind.Refactor)
                )),
            },
            metadata: {
                description: 'Refactor...',
                args: [{ name: 'args', schema: argsSchema }]
            }
        });
    }
    run(_accessor, editor, userArgs) {
        const args = CodeActionCommandArgs.fromUser(userArgs, {
            kind: CodeActionKind.Refactor,
            apply: "never"
        });
        return triggerCodeActionsForEditorSelection(editor, typeof userArgs?.kind === 'string'
            ? args.preferred
                ? ( localizeWithPath(
            'vs/editor/contrib/codeAction/browser/codeActionCommands',
            'editor.action.refactor.noneMessage.preferred.kind',
            "No preferred refactorings for '{0}' available",
            userArgs.kind
        ))
                : ( localizeWithPath(
            'vs/editor/contrib/codeAction/browser/codeActionCommands',
            'editor.action.refactor.noneMessage.kind',
            "No refactorings for '{0}' available",
            userArgs.kind
        ))
            : args.preferred
                ? ( localizeWithPath(
            'vs/editor/contrib/codeAction/browser/codeActionCommands',
            'editor.action.refactor.noneMessage.preferred',
            "No preferred refactorings available"
        ))
                : ( localizeWithPath(
            'vs/editor/contrib/codeAction/browser/codeActionCommands',
            'editor.action.refactor.noneMessage',
            "No refactorings available"
        )), {
            include: CodeActionKind.Refactor.contains(args.kind) ? args.kind : HierarchicalKind.None,
            onlyIncludePreferredActions: args.preferred
        }, args.apply, CodeActionTriggerSource.Refactor);
    }
}
class SourceAction extends EditorAction {
    constructor() {
        super({
            id: sourceActionCommandId,
            label: ( localizeWithPath(
                'vs/editor/contrib/codeAction/browser/codeActionCommands',
                'source.label',
                "Source Action..."
            )),
            alias: 'Source Action...',
            precondition: ( ContextKeyExpr.and(EditorContextKeys.writable, EditorContextKeys.hasCodeActionsProvider)),
            contextMenuOpts: {
                group: '1_modification',
                order: 2.1,
                when: ( ContextKeyExpr.and(
                    EditorContextKeys.writable,
                    contextKeyForSupportedActions(CodeActionKind.Source)
                )),
            },
            metadata: {
                description: 'Source Action...',
                args: [{ name: 'args', schema: argsSchema }]
            }
        });
    }
    run(_accessor, editor, userArgs) {
        const args = CodeActionCommandArgs.fromUser(userArgs, {
            kind: CodeActionKind.Source,
            apply: "never"
        });
        return triggerCodeActionsForEditorSelection(editor, typeof userArgs?.kind === 'string'
            ? args.preferred
                ? ( localizeWithPath(
            'vs/editor/contrib/codeAction/browser/codeActionCommands',
            'editor.action.source.noneMessage.preferred.kind',
            "No preferred source actions for '{0}' available",
            userArgs.kind
        ))
                : ( localizeWithPath(
            'vs/editor/contrib/codeAction/browser/codeActionCommands',
            'editor.action.source.noneMessage.kind',
            "No source actions for '{0}' available",
            userArgs.kind
        ))
            : args.preferred
                ? ( localizeWithPath(
            'vs/editor/contrib/codeAction/browser/codeActionCommands',
            'editor.action.source.noneMessage.preferred',
            "No preferred source actions available"
        ))
                : ( localizeWithPath(
            'vs/editor/contrib/codeAction/browser/codeActionCommands',
            'editor.action.source.noneMessage',
            "No source actions available"
        )), {
            include: CodeActionKind.Source.contains(args.kind) ? args.kind : HierarchicalKind.None,
            includeSourceActions: true,
            onlyIncludePreferredActions: args.preferred,
        }, args.apply, CodeActionTriggerSource.SourceAction);
    }
}
class OrganizeImportsAction extends EditorAction {
    constructor() {
        super({
            id: organizeImportsCommandId,
            label: ( localizeWithPath(
                'vs/editor/contrib/codeAction/browser/codeActionCommands',
                'organizeImports.label',
                "Organize Imports"
            )),
            alias: 'Organize Imports',
            precondition: ( ContextKeyExpr.and(
                EditorContextKeys.writable,
                contextKeyForSupportedActions(CodeActionKind.SourceOrganizeImports)
            )),
            kbOpts: {
                kbExpr: EditorContextKeys.textInputFocus,
                primary: 1024  | 512  | 45 ,
                weight: 100
            },
        });
    }
    run(_accessor, editor) {
        return triggerCodeActionsForEditorSelection(editor, ( localizeWithPath(
            'vs/editor/contrib/codeAction/browser/codeActionCommands',
            'editor.action.organize.noneMessage',
            "No organize imports action available"
        )), { include: CodeActionKind.SourceOrganizeImports, includeSourceActions: true }, "ifSingle" , CodeActionTriggerSource.OrganizeImports);
    }
}
class FixAllAction extends EditorAction {
    constructor() {
        super({
            id: fixAllCommandId,
            label: ( localizeWithPath(
                'vs/editor/contrib/codeAction/browser/codeActionCommands',
                'fixAll.label',
                "Fix All"
            )),
            alias: 'Fix All',
            precondition: ( ContextKeyExpr.and(
                EditorContextKeys.writable,
                contextKeyForSupportedActions(CodeActionKind.SourceFixAll)
            ))
        });
    }
    run(_accessor, editor) {
        return triggerCodeActionsForEditorSelection(editor, ( localizeWithPath(
            'vs/editor/contrib/codeAction/browser/codeActionCommands',
            'fixAll.noneMessage',
            "No fix all action available"
        )), { include: CodeActionKind.SourceFixAll, includeSourceActions: true }, "ifSingle" , CodeActionTriggerSource.FixAll);
    }
}
class AutoFixAction extends EditorAction {
    constructor() {
        super({
            id: autoFixCommandId,
            label: ( localizeWithPath(
                'vs/editor/contrib/codeAction/browser/codeActionCommands',
                'autoFix.label',
                "Auto Fix..."
            )),
            alias: 'Auto Fix...',
            precondition: ( ContextKeyExpr.and(
                EditorContextKeys.writable,
                contextKeyForSupportedActions(CodeActionKind.QuickFix)
            )),
            kbOpts: {
                kbExpr: EditorContextKeys.textInputFocus,
                primary: 512  | 1024  | 89 ,
                mac: {
                    primary: 2048  | 512  | 89
                },
                weight: 100
            }
        });
    }
    run(_accessor, editor) {
        return triggerCodeActionsForEditorSelection(editor, ( localizeWithPath(
            'vs/editor/contrib/codeAction/browser/codeActionCommands',
            'editor.action.autoFix.noneMessage',
            "No auto fixes available"
        )), {
            include: CodeActionKind.QuickFix,
            onlyIncludePreferredActions: true
        }, "ifSingle" , CodeActionTriggerSource.AutoFix);
    }
}
export { AutoFixAction, CodeActionCommand, FixAllAction, OrganizeImportsAction, QuickFixAction, RefactorAction, SourceAction };
