import { localize2WithPath, localizeWithPath } from '../../../../nls.js';
import { MenuRegistry, MenuId } from '../../../../platform/actions/common/actions.js';
import { IConfigurationService } from '../../../../platform/configuration/common/configuration.js';
import { ContextKeyExpr } from '../../../../platform/contextkey/common/contextkey.js';
import { KeybindingsRegistry } from '../../../../platform/keybinding/common/keybindingsRegistry.js';
import { TextDiffEditor } from './textDiffEditor.js';
import { TextCompareEditorVisibleContext, TextCompareEditorActiveContext, ActiveCompareEditorCanSwapContext } from '../../../common/contextkeys.js';
import { DiffEditorInput } from '../../../common/editor/diffEditorInput.js';
import { IEditorService } from '../../../services/editor/common/editorService.js';
const TOGGLE_DIFF_SIDE_BY_SIDE = 'toggle.diff.renderSideBySide';
const GOTO_NEXT_CHANGE = 'workbench.action.compareEditor.nextChange';
const GOTO_PREVIOUS_CHANGE = 'workbench.action.compareEditor.previousChange';
const DIFF_FOCUS_PRIMARY_SIDE = 'workbench.action.compareEditor.focusPrimarySide';
const DIFF_FOCUS_SECONDARY_SIDE = 'workbench.action.compareEditor.focusSecondarySide';
const DIFF_FOCUS_OTHER_SIDE = 'workbench.action.compareEditor.focusOtherSide';
const DIFF_OPEN_SIDE = 'workbench.action.compareEditor.openSide';
const TOGGLE_DIFF_IGNORE_TRIM_WHITESPACE = 'toggle.diff.ignoreTrimWhitespace';
const DIFF_SWAP_SIDES = 'workbench.action.compareEditor.swapSides';
function registerDiffEditorCommands() {
    KeybindingsRegistry.registerCommandAndKeybindingRule({
        id: GOTO_NEXT_CHANGE,
        weight: 200 ,
        when: TextCompareEditorVisibleContext,
        primary: 512  | 63 ,
        handler: accessor => navigateInDiffEditor(accessor, true)
    });
    MenuRegistry.appendMenuItem(MenuId.CommandPalette, {
        command: {
            id: GOTO_NEXT_CHANGE,
            title: ( localize2WithPath(
                'vs/workbench/browser/parts/editor/diffEditorCommands',
                'compare.nextChange',
                'Go to Next Change'
            )),
        }
    });
    KeybindingsRegistry.registerCommandAndKeybindingRule({
        id: GOTO_PREVIOUS_CHANGE,
        weight: 200 ,
        when: TextCompareEditorVisibleContext,
        primary: 512  | 1024  | 63 ,
        handler: accessor => navigateInDiffEditor(accessor, false)
    });
    MenuRegistry.appendMenuItem(MenuId.CommandPalette, {
        command: {
            id: GOTO_PREVIOUS_CHANGE,
            title: ( localize2WithPath(
                'vs/workbench/browser/parts/editor/diffEditorCommands',
                'compare.previousChange',
                'Go to Previous Change'
            )),
        }
    });
    function getActiveTextDiffEditor(accessor) {
        const editorService = accessor.get(IEditorService);
        for (const editor of [editorService.activeEditorPane, ...editorService.visibleEditorPanes]) {
            if (editor instanceof TextDiffEditor) {
                return editor;
            }
        }
        return undefined;
    }
    function navigateInDiffEditor(accessor, next) {
        const activeTextDiffEditor = getActiveTextDiffEditor(accessor);
        if (activeTextDiffEditor) {
            activeTextDiffEditor.getControl()?.goToDiff(next ? 'next' : 'previous');
        }
    }
    let FocusTextDiffEditorMode;
    ( (function(FocusTextDiffEditorMode) {
        FocusTextDiffEditorMode[FocusTextDiffEditorMode["Original"] = 0] = "Original";
        FocusTextDiffEditorMode[FocusTextDiffEditorMode["Modified"] = 1] = "Modified";
        FocusTextDiffEditorMode[FocusTextDiffEditorMode["Toggle"] = 2] = "Toggle";
    })(FocusTextDiffEditorMode || (FocusTextDiffEditorMode = {})));
    function focusInDiffEditor(accessor, mode) {
        const activeTextDiffEditor = getActiveTextDiffEditor(accessor);
        if (activeTextDiffEditor) {
            switch (mode) {
                case FocusTextDiffEditorMode.Original:
                    activeTextDiffEditor.getControl()?.getOriginalEditor().focus();
                    break;
                case FocusTextDiffEditorMode.Modified:
                    activeTextDiffEditor.getControl()?.getModifiedEditor().focus();
                    break;
                case FocusTextDiffEditorMode.Toggle:
                    if (activeTextDiffEditor.getControl()?.getModifiedEditor().hasWidgetFocus()) {
                        return focusInDiffEditor(accessor, FocusTextDiffEditorMode.Original);
                    }
                    else {
                        return focusInDiffEditor(accessor, FocusTextDiffEditorMode.Modified);
                    }
            }
        }
    }
    function toggleDiffSideBySide(accessor) {
        const configurationService = accessor.get(IConfigurationService);
        const newValue = !configurationService.getValue('diffEditor.renderSideBySide');
        configurationService.updateValue('diffEditor.renderSideBySide', newValue);
    }
    function toggleDiffIgnoreTrimWhitespace(accessor) {
        const configurationService = accessor.get(IConfigurationService);
        const newValue = !configurationService.getValue('diffEditor.ignoreTrimWhitespace');
        configurationService.updateValue('diffEditor.ignoreTrimWhitespace', newValue);
    }
    async function swapDiffSides(accessor) {
        const editorService = accessor.get(IEditorService);
        const diffEditor = getActiveTextDiffEditor(accessor);
        const activeGroup = diffEditor?.group;
        const diffInput = diffEditor?.input;
        if (!diffEditor || typeof activeGroup === 'undefined' || !(diffInput instanceof DiffEditorInput) || !diffInput.modified.resource) {
            return;
        }
        const untypedDiffInput = diffInput.toUntyped({ preserveViewState: activeGroup.id, preserveResource: true });
        if (!untypedDiffInput) {
            return;
        }
        if (diffInput.modified.isModified() && editorService.findEditors({ resource: diffInput.modified.resource, typeId: diffInput.modified.typeId, editorId: diffInput.modified.editorId }).length === 0) {
            await editorService.openEditor({
                ...untypedDiffInput.modified,
                options: {
                    ...untypedDiffInput.modified.options,
                    pinned: true,
                    inactive: true
                }
            }, activeGroup);
        }
        await editorService.replaceEditors([
            {
                editor: diffInput,
                replacement: {
                    ...untypedDiffInput,
                    original: untypedDiffInput.modified,
                    modified: untypedDiffInput.original,
                    options: {
                        ...untypedDiffInput.options,
                        pinned: true
                    }
                }
            }
        ], activeGroup);
    }
    KeybindingsRegistry.registerCommandAndKeybindingRule({
        id: TOGGLE_DIFF_SIDE_BY_SIDE,
        weight: 200 ,
        when: undefined,
        primary: undefined,
        handler: accessor => toggleDiffSideBySide(accessor)
    });
    KeybindingsRegistry.registerCommandAndKeybindingRule({
        id: DIFF_FOCUS_PRIMARY_SIDE,
        weight: 200 ,
        when: undefined,
        primary: undefined,
        handler: accessor => focusInDiffEditor(accessor, FocusTextDiffEditorMode.Modified)
    });
    KeybindingsRegistry.registerCommandAndKeybindingRule({
        id: DIFF_FOCUS_SECONDARY_SIDE,
        weight: 200 ,
        when: undefined,
        primary: undefined,
        handler: accessor => focusInDiffEditor(accessor, FocusTextDiffEditorMode.Original)
    });
    KeybindingsRegistry.registerCommandAndKeybindingRule({
        id: DIFF_FOCUS_OTHER_SIDE,
        weight: 200 ,
        when: undefined,
        primary: undefined,
        handler: accessor => focusInDiffEditor(accessor, FocusTextDiffEditorMode.Toggle)
    });
    KeybindingsRegistry.registerCommandAndKeybindingRule({
        id: TOGGLE_DIFF_IGNORE_TRIM_WHITESPACE,
        weight: 200 ,
        when: undefined,
        primary: undefined,
        handler: accessor => toggleDiffIgnoreTrimWhitespace(accessor)
    });
    KeybindingsRegistry.registerCommandAndKeybindingRule({
        id: DIFF_SWAP_SIDES,
        weight: 200 ,
        when: undefined,
        primary: undefined,
        handler: accessor => swapDiffSides(accessor)
    });
    MenuRegistry.appendMenuItem(MenuId.CommandPalette, {
        command: {
            id: TOGGLE_DIFF_SIDE_BY_SIDE,
            title: ( localize2WithPath(
                'vs/workbench/browser/parts/editor/diffEditorCommands',
                'toggleInlineView',
                "Toggle Inline View"
            )),
            category: ( localizeWithPath(
                'vs/workbench/browser/parts/editor/diffEditorCommands',
                'compare',
                "Compare"
            ))
        },
        when: TextCompareEditorActiveContext
    });
    MenuRegistry.appendMenuItem(MenuId.CommandPalette, {
        command: {
            id: DIFF_SWAP_SIDES,
            title: ( localize2WithPath(
                'vs/workbench/browser/parts/editor/diffEditorCommands',
                'swapDiffSides',
                "Swap Left and Right Editor Side"
            )),
            category: ( localizeWithPath(
                'vs/workbench/browser/parts/editor/diffEditorCommands',
                'compare',
                "Compare"
            ))
        },
        when: ( ContextKeyExpr.and(TextCompareEditorActiveContext, ActiveCompareEditorCanSwapContext))
    });
}
export { DIFF_FOCUS_OTHER_SIDE, DIFF_FOCUS_PRIMARY_SIDE, DIFF_FOCUS_SECONDARY_SIDE, DIFF_OPEN_SIDE, DIFF_SWAP_SIDES, GOTO_NEXT_CHANGE, GOTO_PREVIOUS_CHANGE, TOGGLE_DIFF_IGNORE_TRIM_WHITESPACE, TOGGLE_DIFF_SIDE_BY_SIDE, registerDiffEditorCommands };
