
import { registerCss } from '../../../../../../../css.js';
import { __decorate, __param } from '../../../../../../../external/tslib/tslib.es6.js';
import * as keybindings from './media/keybindings.css';
import { localize } from '../../../../nls.js';
import { OS } from '../../../../base/common/platform.js';
import { DisposableStore, toDisposable, Disposable } from '../../../../base/common/lifecycle.js';
import { Emitter } from '../../../../base/common/event.js';
import { KeybindingLabel } from '../../../../base/browser/ui/keybindingLabel/keybindingLabel.js';
import { Widget } from '../../../../base/browser/ui/widget.js';
import { KeyCode } from '../../../../base/common/keyCodes.js';
import { addDisposableListener, EventType, createElement, append, $, clearNode, createTextNode, Dimension } from '../../../../base/browser/dom.js';
import { alert } from '../../../../base/browser/ui/aria/aria.js';
import { StandardKeyboardEvent } from '../../../../base/browser/keyboardEvent.js';
import { createFastDomNode } from '../../../../base/browser/fastDomNode.js';
import { IKeybindingService } from '../../../../platform/keybinding/common/keybinding.service.js';
import { IContextViewService } from '../../../../platform/contextview/browser/contextView.service.js';
import { IInstantiationService } from '../../../../platform/instantiation/common/instantiation.js';
import { asCssVariable } from '../../../../platform/theme/common/colorUtils.js';
import '../../../../platform/theme/common/colors/baseColors.js';
import '../../../../platform/theme/common/colors/chartsColors.js';
import { editorWidgetBackground, editorWidgetForeground } from '../../../../platform/theme/common/colors/editorColors.js';
import '../../../../platform/theme/common/colors/inputColors.js';
import '../../../../platform/theme/common/colors/listColors.js';
import '../../../../platform/theme/common/colors/menuColors.js';
import '../../../../platform/theme/common/colors/minimapColors.js';
import '../../../../platform/theme/common/colors/miscColors.js';
import '../../../../platform/theme/common/colors/quickpickColors.js';
import '../../../../platform/theme/common/colors/searchColors.js';
import { ScrollType } from '../../../../editor/common/editorCommon.js';
import { SearchWidget } from './preferencesWidgets.js';
import { Promises, timeout } from '../../../../base/common/async.js';
import { IContextKeyService } from '../../../../platform/contextkey/common/contextkey.service.js';
import { defaultInputBoxStyles, defaultKeybindingLabelStyles } from '../../../../platform/theme/browser/defaultStyles.js';

var DefineKeybindingWidget_1, DefineKeybindingOverlayWidget_1;
registerCss(keybindings);
let KeybindingsSearchWidget = class KeybindingsSearchWidget extends SearchWidget {
    constructor(
        parent,
        options,
        contextViewService,
        instantiationService,
        contextKeyService,
        keybindingService
    ) {
        super(
            parent,
            options,
            contextViewService,
            instantiationService,
            contextKeyService,
            keybindingService
        );
        this.recordDisposables = this._register(( new DisposableStore()));
        this._onKeybinding = this._register(( new Emitter()));
        this.onKeybinding = this._onKeybinding.event;
        this._onEnter = this._register(( new Emitter()));
        this.onEnter = this._onEnter.event;
        this._onEscape = this._register(( new Emitter()));
        this.onEscape = this._onEscape.event;
        this._onBlur = this._register(( new Emitter()));
        this.onBlur = this._onBlur.event;
        this._register(toDisposable(() => this.stopRecordingKeys()));
        this._chords = null;
        this._inputValue = "";
    }
    clear() {
        this._chords = null;
        super.clear();
    }
    startRecordingKeys() {
        this.recordDisposables.add(addDisposableListener(
            this.inputBox.inputElement,
            EventType.KEY_DOWN,
            e => this._onKeyDown(( new StandardKeyboardEvent(e)))
        ));
        this.recordDisposables.add(
            addDisposableListener(this.inputBox.inputElement, EventType.BLUR, () => this._onBlur.fire())
        );
        this.recordDisposables.add(
            addDisposableListener(this.inputBox.inputElement, EventType.INPUT, () => {
                this.setInputValue(this._inputValue);
            })
        );
    }
    stopRecordingKeys() {
        this._chords = null;
        this.recordDisposables.clear();
    }
    setInputValue(value) {
        this._inputValue = value;
        this.inputBox.value = this._inputValue;
    }
    _onKeyDown(keyboardEvent) {
        keyboardEvent.preventDefault();
        keyboardEvent.stopPropagation();
        const options = this.options;
        if (!options.recordEnter && keyboardEvent.equals(KeyCode.Enter)) {
            this._onEnter.fire();
            return;
        }
        if (keyboardEvent.equals(KeyCode.Escape)) {
            this._onEscape.fire();
            return;
        }
        this.printKeybinding(keyboardEvent);
    }
    printKeybinding(keyboardEvent) {
        const keybinding = this.keybindingService.resolveKeyboardEvent(keyboardEvent);
        const info = `code: ${keyboardEvent.browserEvent.code}, keyCode: ${keyboardEvent.browserEvent.keyCode}, key: ${keyboardEvent.browserEvent.key} => UI: ${keybinding.getAriaLabel()}, user settings: ${keybinding.getUserSettingsLabel()}, dispatch: ${keybinding.getDispatchChords()[0]}`;
        const options = this.options;
        if (!this._chords) {
            this._chords = [];
        }
        const hasIncompleteChord = this._chords.length > 0 && this._chords[this._chords.length - 1].getDispatchChords()[0] === null;
        if (hasIncompleteChord) {
            this._chords[this._chords.length - 1] = keybinding;
        } else {
            if (this._chords.length === 2) {
                this._chords = [];
            }
            this._chords.push(keybinding);
        }
        const value = ( this._chords.map(keybinding => keybinding.getUserSettingsLabel() || "")).join(" ");
        this.setInputValue(options.quoteRecordedKeys ? `"${value}"` : value);
        this.inputBox.inputElement.title = info;
        this._onKeybinding.fire(this._chords);
    }
};
KeybindingsSearchWidget = ( __decorate([( __param(2, IContextViewService)), ( __param(3, IInstantiationService)), ( __param(4, IContextKeyService)), ( __param(5, IKeybindingService))], KeybindingsSearchWidget));
let DefineKeybindingWidget = class DefineKeybindingWidget extends Widget {
    static {
        DefineKeybindingWidget_1 = this;
    }
    static {
        this.WIDTH = 400;
    }
    static {
        this.HEIGHT = 110;
    }
    constructor(parent, instantiationService) {
        super();
        this.instantiationService = instantiationService;
        this._keybindingDisposables = this._register(( new DisposableStore()));
        this._chords = null;
        this._isVisible = false;
        this._onHide = this._register(( new Emitter()));
        this._onDidChange = this._register(( new Emitter()));
        this.onDidChange = this._onDidChange.event;
        this._onShowExistingKeybindings = this._register(( new Emitter()));
        this.onShowExistingKeybidings = this._onShowExistingKeybindings.event;
        this._domNode = createFastDomNode(createElement("div"));
        this._domNode.setDisplay("none");
        this._domNode.setClassName("defineKeybindingWidget");
        this._domNode.setWidth(DefineKeybindingWidget_1.WIDTH);
        this._domNode.setHeight(DefineKeybindingWidget_1.HEIGHT);
        const message = ( localize(12375, "Press desired key combination and then press ENTER."));
        append(this._domNode.domNode, $(".message", undefined, message));
        this._domNode.domNode.style.backgroundColor = asCssVariable(editorWidgetBackground);
        this._domNode.domNode.style.color = asCssVariable(editorWidgetForeground);
        this._keybindingInputWidget = this._register(
            this.instantiationService.createInstance(KeybindingsSearchWidget, this._domNode.domNode, {
                ariaLabel: message,
                history: ( new Set([])),
                inputBoxStyles: defaultInputBoxStyles
            })
        );
        this._keybindingInputWidget.startRecordingKeys();
        this._register(
            this._keybindingInputWidget.onKeybinding(keybinding => this.onKeybinding(keybinding))
        );
        this._register(this._keybindingInputWidget.onEnter(() => this.hide()));
        this._register(this._keybindingInputWidget.onEscape(() => this.clearOrHide()));
        this._register(this._keybindingInputWidget.onBlur(() => this.onCancel()));
        this._outputNode = append(this._domNode.domNode, $(".output"));
        this._showExistingKeybindingsNode = append(this._domNode.domNode, $(".existing"));
        if (parent) {
            append(parent, this._domNode.domNode);
        }
    }
    get domNode() {
        return this._domNode.domNode;
    }
    define() {
        this._keybindingInputWidget.clear();
        return Promises.withAsyncBody(async c => {
            if (!this._isVisible) {
                this._isVisible = true;
                this._domNode.setDisplay("block");
                this._chords = null;
                this._keybindingInputWidget.setInputValue("");
                clearNode(this._outputNode);
                clearNode(this._showExistingKeybindingsNode);
                await timeout(0);
                this._keybindingInputWidget.focus();
            }
            const disposable = this._onHide.event(() => {
                c(this.getUserSettingsLabel());
                disposable.dispose();
            });
        });
    }
    layout(layout) {
        const top = Math.round((layout.height - DefineKeybindingWidget_1.HEIGHT) / 2);
        this._domNode.setTop(top);
        const left = Math.round((layout.width - DefineKeybindingWidget_1.WIDTH) / 2);
        this._domNode.setLeft(left);
    }
    printExisting(numberOfExisting) {
        if (numberOfExisting > 0) {
            const existingElement = $("span.existingText");
            const text = numberOfExisting === 1 ? ( localize(12376, "1 existing command has this keybinding", numberOfExisting)) : ( localize(12377, "{0} existing commands have this keybinding", numberOfExisting));
            append(existingElement, createTextNode(text));
            alert(text);
            this._showExistingKeybindingsNode.appendChild(existingElement);
            existingElement.onmousedown = e => {
                e.preventDefault();
            };
            existingElement.onmouseup = e => {
                e.preventDefault();
            };
            existingElement.onclick = () => {
                this._onShowExistingKeybindings.fire(this.getUserSettingsLabel());
            };
        }
    }
    onKeybinding(keybinding) {
        this._keybindingDisposables.clear();
        this._chords = keybinding;
        clearNode(this._outputNode);
        clearNode(this._showExistingKeybindingsNode);
        const firstLabel = this._keybindingDisposables.add(( new KeybindingLabel(this._outputNode, OS, defaultKeybindingLabelStyles)));
        firstLabel.set(this._chords?.[0] ?? undefined);
        if (this._chords) {
            for (let i = 1; i < this._chords.length; i++) {
                this._outputNode.appendChild(createTextNode(( localize(12378, "chord to"))));
                const chordLabel = this._keybindingDisposables.add(( new KeybindingLabel(this._outputNode, OS, defaultKeybindingLabelStyles)));
                chordLabel.set(this._chords[i]);
            }
        }
        const label = this.getUserSettingsLabel();
        if (label) {
            this._onDidChange.fire(label);
        }
    }
    getUserSettingsLabel() {
        let label = null;
        if (this._chords) {
            label = ( this._chords.map(keybinding => keybinding.getUserSettingsLabel())).join(" ");
        }
        return label;
    }
    onCancel() {
        this._chords = null;
        this.hide();
    }
    clearOrHide() {
        if (this._chords === null) {
            this.hide();
        } else {
            this._chords = null;
            this._keybindingInputWidget.clear();
            clearNode(this._outputNode);
            clearNode(this._showExistingKeybindingsNode);
        }
    }
    hide() {
        this._domNode.setDisplay("none");
        this._isVisible = false;
        this._onHide.fire();
    }
};
DefineKeybindingWidget = DefineKeybindingWidget_1 = ( __decorate([( __param(1, IInstantiationService))], DefineKeybindingWidget));
let DefineKeybindingOverlayWidget = class DefineKeybindingOverlayWidget extends Disposable {
    static {
        DefineKeybindingOverlayWidget_1 = this;
    }
    static {
        this.ID = "editor.contrib.defineKeybindingWidget";
    }
    constructor(_editor, instantiationService) {
        super();
        this._editor = _editor;
        this._widget = this._register(instantiationService.createInstance(DefineKeybindingWidget, null));
        this._editor.addOverlayWidget(this);
    }
    getId() {
        return DefineKeybindingOverlayWidget_1.ID;
    }
    getDomNode() {
        return this._widget.domNode;
    }
    getPosition() {
        return {
            preference: null
        };
    }
    dispose() {
        this._editor.removeOverlayWidget(this);
        super.dispose();
    }
    start() {
        if (this._editor.hasModel()) {
            this._editor.revealPositionInCenterIfOutsideViewport(this._editor.getPosition(), ScrollType.Smooth);
        }
        const layoutInfo = this._editor.getLayoutInfo();
        this._widget.layout(new Dimension(layoutInfo.width, layoutInfo.height));
        return this._widget.define();
    }
};
DefineKeybindingOverlayWidget = DefineKeybindingOverlayWidget_1 = ( __decorate([( __param(1, IInstantiationService))], DefineKeybindingOverlayWidget));

export { DefineKeybindingOverlayWidget, DefineKeybindingWidget, KeybindingsSearchWidget };
