import { __decorate, __param } from '../../../../../../../external/tslib/tslib.es6.js';
import { append, setVisibility, clearNode, Dimension, getTotalWidth, $ as $$1 } from '../../../../base/browser/dom.js';
import { DEFAULT_FONT_FAMILY } from '../../../../base/browser/fonts.js';
import { status } from '../../../../base/browser/ui/aria/aria.js';
import { Checkbox } from '../../../../base/browser/ui/toggle/toggle.js';
import { Codicon } from '../../../../base/common/codicons.js';
import { Emitter } from '../../../../base/common/event.js';
import { HistoryNavigator } from '../../../../base/common/history.js';
import { Disposable, DisposableStore } from '../../../../base/common/lifecycle.js';
import { isMacintosh } from '../../../../base/common/platform.js';
import { URI } from '../../../../base/common/uri.js';
import { EditorExtensionsRegistry } from '../../../../editor/browser/editorExtensions.js';
import { CodeEditorWidget } from '../../../../editor/browser/widget/codeEditor/codeEditorWidget.js';
import { IModelService } from '../../../../editor/common/services/model.js';
import { HoverController } from '../../../../editor/contrib/hover/browser/hover.js';
import { localizeWithPath } from '../../../../nls.js';
import { IAccessibilityService } from '../../../../platform/accessibility/common/accessibility.js';
import { DropdownWithPrimaryActionViewItem } from '../../../../platform/actions/browser/dropdownWithPrimaryActionViewItem.js';
import { createAndFillInActionBarActions } from '../../../../platform/actions/browser/menuEntryActionViewItem.js';
import { MenuWorkbenchToolBar } from '../../../../platform/actions/browser/toolbar.js';
import { MenuItemAction, MenuId, IMenuService } from '../../../../platform/actions/common/actions.js';
import { IConfigurationService } from '../../../../platform/configuration/common/configuration.js';
import { IContextKeyService } from '../../../../platform/contextkey/common/contextkey.js';
import { IContextMenuService } from '../../../../platform/contextview/browser/contextView.js';
import { registerAndCreateHistoryNavigationContext } from '../../../../platform/history/browser/contextScopedHistoryWidget.js';
import { IInstantiationService } from '../../../../platform/instantiation/common/instantiation.js';
import { ServiceCollection } from '../../../../platform/instantiation/common/serviceCollection.js';
import { IKeybindingService } from '../../../../platform/keybinding/common/keybinding.js';
import { INotificationService } from '../../../../platform/notification/common/notification.js';
import { defaultCheckboxStyles } from '../../../../platform/theme/browser/defaultStyles.js';
import { asCssVariableWithDefault } from '../../../../platform/theme/common/colorUtils.js';
import '../../../../platform/theme/common/colors/baseColors.js';
import '../../../../platform/theme/common/colors/chartsColors.js';
import '../../../../platform/theme/common/colors/editorColors.js';
import { inputBackground, checkboxBorder } from '../../../../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 { IThemeService } from '../../../../platform/theme/common/themeService.js';
import { ChatSubmitSecondaryAgentEditorAction } from './actions/chatActions.js';
import { SubmitAction, CancelAction } from './actions/chatExecuteActions.js';
import { ChatFollowups } from './chatFollowups.js';
import { ChatAgentLocation, IChatAgentService } from '../common/chatAgents.js';
import { CONTEXT_CHAT_INPUT_HAS_TEXT, CONTEXT_CHAT_INPUT_CURSOR_AT_TOP, CONTEXT_CHAT_INPUT_HAS_FOCUS, CONTEXT_IN_CHAT_INPUT } from '../common/chatContextKeys.js';
import { IChatWidgetHistoryService } from '../common/chatWidgetHistoryService.js';
import { getSimpleEditorOptions, getSimpleCodeEditorWidgetOptions } from '../../codeEditor/browser/simpleEditorOptions.js';
var ChatInputPart_1;
const $ = $$1;
const INPUT_EDITOR_MAX_HEIGHT = 250;
let ChatInputPart = class ChatInputPart extends Disposable {
    static { ChatInputPart_1 = this; }
    static { this.INPUT_SCHEME = 'chatSessionInput'; }
    static { this._counter = 0; }
    get implicitContextEnabled() {
        return this.implicitContextCheckbox.checked;
    }
    get inputPartHeight() {
        return this._inputPartHeight;
    }
    get inputEditor() {
        return this._inputEditor;
    }
    constructor(
    location, options, historyService, modelService, instantiationService, contextKeyService, configurationService, keybindingService, accessibilityService) {
        super();
        this.location = location;
        this.options = options;
        this.historyService = historyService;
        this.modelService = modelService;
        this.instantiationService = instantiationService;
        this.contextKeyService = contextKeyService;
        this.configurationService = configurationService;
        this.keybindingService = keybindingService;
        this.accessibilityService = accessibilityService;
        this._onDidLoadInputState = this._register(( new Emitter()));
        this.onDidLoadInputState = this._onDidLoadInputState.event;
        this._onDidChangeHeight = this._register(( new Emitter()));
        this.onDidChangeHeight = this._onDidChangeHeight.event;
        this._onDidFocus = this._register(( new Emitter()));
        this.onDidFocus = this._onDidFocus.event;
        this._onDidBlur = this._register(( new Emitter()));
        this.onDidBlur = this._onDidBlur.event;
        this._onDidAcceptFollowup = this._register(( new Emitter()));
        this.onDidAcceptFollowup = this._onDidAcceptFollowup.event;
        this.inputEditorHeight = 0;
        this.followupsDisposables = this._register(( new DisposableStore()));
        this.implicitContextSettingEnabled = false;
        this._inputPartHeight = 0;
        this.onHistoryEntry = false;
        this.inHistoryNavigation = false;
        this.inputUri = ( URI.parse(`${ChatInputPart_1.INPUT_SCHEME}:input-${ChatInputPart_1._counter++}`));
        this.inputEditorHasText = CONTEXT_CHAT_INPUT_HAS_TEXT.bindTo(contextKeyService);
        this.chatCursorAtTop = CONTEXT_CHAT_INPUT_CURSOR_AT_TOP.bindTo(contextKeyService);
        this.inputEditorHasFocus = CONTEXT_CHAT_INPUT_HAS_FOCUS.bindTo(contextKeyService);
        this.history = ( new HistoryNavigator([], 5));
        this._register(this.historyService.onDidClearHistory(() => this.history.clear()));
        this.implicitContextSettingEnabled = this.configurationService.getValue('chat.experimental.implicitContext');
        this._register(this.configurationService.onDidChangeConfiguration(e => {
            if (e.affectsConfiguration("accessibility.verbosity.panelChat" )) {
                this.inputEditor.updateOptions({ ariaLabel: this._getAriaLabel() });
            }
            if (e.affectsConfiguration('chat.experimental.implicitContext')) {
                this.implicitContextSettingEnabled = this.configurationService.getValue('chat.experimental.implicitContext');
            }
        }));
    }
    _getAriaLabel() {
        const verbose = this.configurationService.getValue("accessibility.verbosity.panelChat" );
        if (verbose) {
            const kbLabel = this.keybindingService.lookupKeybinding("editor.action.accessibilityHelp" )?.getLabel();
            return kbLabel ? ( localizeWithPath(
                'vs/workbench/contrib/chat/browser/chatInputPart',
                'actions.chat.accessibiltyHelp',
                "Chat Input,  Type to ask questions or type / for topics, press enter to send out the request. Use {0} for Chat Accessibility Help.",
                kbLabel
            )) : ( localizeWithPath(
                'vs/workbench/contrib/chat/browser/chatInputPart',
                'chatInput.accessibilityHelpNoKb',
                "Chat Input,  Type code here and press Enter to run. Use the Chat Accessibility Help command for more information."
            ));
        }
        return ( localizeWithPath(
            'vs/workbench/contrib/chat/browser/chatInputPart',
            'chatInput',
            "Chat Input"
        ));
    }
    setState(providerId, inputValue) {
        this.providerId = providerId;
        const history = this.historyService.getHistory(providerId);
        this.history = ( new HistoryNavigator(history, 50));
        if (typeof inputValue === 'string') {
            this.setValue(inputValue);
        }
    }
    get element() {
        return this.container;
    }
    showPreviousValue() {
        this.navigateHistory(true);
    }
    showNextValue() {
        this.navigateHistory(false);
    }
    navigateHistory(previous) {
        const historyEntry = (previous ?
            (this.history.previous() ?? this.history.first()) : this.history.next())
            ?? { text: '' };
        this.onHistoryEntry = previous || this.history.current() !== null;
        status(historyEntry.text);
        this.inHistoryNavigation = true;
        this.setValue(historyEntry.text);
        this.inHistoryNavigation = false;
        this._onDidLoadInputState.fire(historyEntry.state);
        if (previous) {
            this._inputEditor.setPosition({ lineNumber: 1, column: 1 });
        }
        else {
            const model = this._inputEditor.getModel();
            if (!model) {
                return;
            }
            this._inputEditor.setPosition(getLastPosition(model));
        }
    }
    setValue(value) {
        this.inputEditor.setValue(value);
        this.inputEditor.setPosition({ lineNumber: 1, column: value.length + 1 });
    }
    focus() {
        this._inputEditor.focus();
    }
    hasFocus() {
        return this._inputEditor.hasWidgetFocus();
    }
    async acceptInput(userQuery, inputState) {
        if (userQuery) {
            let element = this.history.getHistory().find(candidate => candidate.text === userQuery);
            if (!element) {
                element = { text: userQuery, state: inputState };
            }
            else {
                element.state = inputState;
            }
            this.history.add(element);
        }
        if (this.accessibilityService.isScreenReaderOptimized() && isMacintosh) {
            this._acceptInputForVoiceover();
        }
        else {
            this._inputEditor.focus();
            this._inputEditor.setValue('');
        }
    }
    _acceptInputForVoiceover() {
        const domNode = this._inputEditor.getDomNode();
        if (!domNode) {
            return;
        }
        this._inputEditorElement.removeChild(domNode);
        this._inputEditor.setValue('');
        this._inputEditorElement.appendChild(domNode);
        this._inputEditor.focus();
    }
    render(container, initialValue, widget) {
        this.container = append(container, $('.interactive-input-part'));
        this.container.classList.toggle('compact', this.options.renderStyle === 'compact');
        this.followupsContainer = append(this.container, $('.interactive-input-followups'));
        this.implicitContextContainer = append(this.container, $('.chat-implicit-context'));
        this.initImplicitContext(this.implicitContextContainer);
        const inputAndSideToolbar = append(this.container, $('.interactive-input-and-side-toolbar'));
        const inputContainer = append(inputAndSideToolbar, $('.interactive-input-and-execute-toolbar'));
        const inputScopedContextKeyService = this._register(this.contextKeyService.createScoped(inputContainer));
        CONTEXT_IN_CHAT_INPUT.bindTo(inputScopedContextKeyService).set(true);
        const scopedInstantiationService = this.instantiationService.createChild(( new ServiceCollection([IContextKeyService, inputScopedContextKeyService])));
        const { historyNavigationBackwardsEnablement, historyNavigationForwardsEnablement } = this._register(registerAndCreateHistoryNavigationContext(inputScopedContextKeyService, this));
        this.historyNavigationBackwardsEnablement = historyNavigationBackwardsEnablement;
        this.historyNavigationForewardsEnablement = historyNavigationForwardsEnablement;
        const options = getSimpleEditorOptions(this.configurationService);
        options.overflowWidgetsDomNode = this.options.editorOverflowWidgetsDomNode;
        options.readOnly = false;
        options.ariaLabel = this._getAriaLabel();
        options.fontFamily = DEFAULT_FONT_FAMILY;
        options.fontSize = 13;
        options.lineHeight = 20;
        options.padding = this.options.renderStyle === 'compact' ? { top: 2, bottom: 2 } : { top: 8, bottom: 8 };
        options.cursorWidth = 1;
        options.wrappingStrategy = 'advanced';
        options.bracketPairColorization = { enabled: false };
        options.suggest = {
            showIcons: false,
            showSnippets: false,
            showWords: true,
            showStatusBar: false,
            insertMode: 'replace',
        };
        options.scrollbar = { ...(options.scrollbar ?? {}), vertical: 'hidden' };
        this._inputEditorElement = append(inputContainer, $('.interactive-input-editor'));
        const editorOptions = getSimpleCodeEditorWidgetOptions();
        editorOptions.contributions?.push(...EditorExtensionsRegistry.getSomeEditorContributions([HoverController.ID]));
        this._inputEditor = this._register(scopedInstantiationService.createInstance(CodeEditorWidget, this._inputEditorElement, options, editorOptions));
        this._register(this._inputEditor.onDidChangeModelContent(() => {
            const currentHeight = Math.min(this._inputEditor.getContentHeight(), INPUT_EDITOR_MAX_HEIGHT);
            if (currentHeight !== this.inputEditorHeight) {
                this.inputEditorHeight = currentHeight;
                this._onDidChangeHeight.fire();
            }
            const model = this._inputEditor.getModel();
            const inputHasText = !!model && model.getValue().trim().length > 0;
            this.inputEditorHasText.set(inputHasText);
            if (!this.inHistoryNavigation) {
                this.onHistoryEntry = false;
            }
            if (!this.onHistoryEntry) {
                this.historyNavigationForewardsEnablement.set(!inputHasText);
                this.historyNavigationBackwardsEnablement.set(!inputHasText);
            }
        }));
        this._register(this._inputEditor.onDidFocusEditorText(() => {
            this.inputEditorHasFocus.set(true);
            this._onDidFocus.fire();
            inputContainer.classList.toggle('focused', true);
        }));
        this._register(this._inputEditor.onDidBlurEditorText(() => {
            this.inputEditorHasFocus.set(false);
            inputContainer.classList.toggle('focused', false);
            this._onDidBlur.fire();
        }));
        this._register(this._inputEditor.onDidChangeCursorPosition(e => {
            const model = this._inputEditor.getModel();
            if (!model) {
                return;
            }
            const atTop = e.position.column === 1 && e.position.lineNumber === 1;
            this.chatCursorAtTop.set(atTop);
            if (this.onHistoryEntry) {
                this.historyNavigationBackwardsEnablement.set(atTop);
                this.historyNavigationForewardsEnablement.set(e.position.equals(getLastPosition(model)));
            }
        }));
        this.toolbar = this._register(this.instantiationService.createInstance(MenuWorkbenchToolBar, inputContainer, this.options.menus.executeToolbar, {
            telemetrySource: this.options.menus.telemetrySource,
            menuOptions: {
                shouldForwardArgs: true
            },
            hiddenItemStrategy: 0 ,
            actionViewItemProvider: (action, options) => {
                if (this.location === ChatAgentLocation.Panel) {
                    if ((action.id === SubmitAction.ID || action.id === CancelAction.ID) && action instanceof MenuItemAction) {
                        const dropdownAction = this.instantiationService.createInstance(MenuItemAction, { id: 'chat.moreExecuteActions', title: ( localizeWithPath(
                            'vs/workbench/contrib/chat/browser/chatInputPart',
                            'notebook.moreExecuteActionsLabel',
                            "More..."
                        )), icon: Codicon.chevronDown }, undefined, undefined, undefined);
                        return this.instantiationService.createInstance(ChatSubmitDropdownActionItem, action, dropdownAction);
                    }
                }
                return undefined;
            }
        }));
        this.toolbar.getElement().classList.add('interactive-execute-toolbar');
        this.toolbar.context = { widget };
        this._register(this.toolbar.onDidChangeMenuItems(() => {
            if (this.cachedDimensions && typeof this.cachedToolbarWidth === 'number' && this.cachedToolbarWidth !== this.toolbar.getItemsWidth()) {
                this.layout(this.cachedDimensions.height, this.cachedDimensions.width);
            }
        }));
        if (this.options.menus.inputSideToolbar) {
            const toolbarSide = this._register(this.instantiationService.createInstance(MenuWorkbenchToolBar, inputAndSideToolbar, this.options.menus.inputSideToolbar, {
                telemetrySource: this.options.menus.telemetrySource,
                menuOptions: {
                    shouldForwardArgs: true
                }
            }));
            this.inputSideToolbarContainer = toolbarSide.getElement();
            toolbarSide.getElement().classList.add('chat-side-toolbar');
            toolbarSide.context = { widget };
        }
        let inputModel = this.modelService.getModel(this.inputUri);
        if (!inputModel) {
            inputModel = this.modelService.createModel('', null, this.inputUri, true);
            this._register(inputModel);
        }
        this.inputModel = inputModel;
        this.inputModel.updateOptions({ bracketColorizationOptions: { enabled: false, independentColorPoolPerBracketType: false } });
        this._inputEditor.setModel(this.inputModel);
        if (initialValue) {
            this.inputModel.setValue(initialValue);
            const lineNumber = this.inputModel.getLineCount();
            this._inputEditor.setPosition({ lineNumber, column: this.inputModel.getLineMaxColumn(lineNumber) });
        }
    }
    initImplicitContext(container) {
        this.implicitContextCheckbox = ( new Checkbox(
            '#selection',
            true,
            { ...defaultCheckboxStyles, checkboxBorder: asCssVariableWithDefault(checkboxBorder, inputBackground) }
        ));
        container.append(this.implicitContextCheckbox.domNode);
        this.implicitContextLabel = append(container, $('span.chat-implicit-context-label'));
        this.implicitContextLabel.textContent = '#selection';
    }
    setImplicitContextKinds(kinds) {
        setVisibility(this.implicitContextSettingEnabled && kinds.length > 0, this.implicitContextContainer);
        this.implicitContextLabel.textContent = ( localizeWithPath('vs/workbench/contrib/chat/browser/chatInputPart', 'use', "Use")) + ' ' + ( kinds.map(k => `#${k}`)).join(', ');
    }
    async renderFollowups(items, response) {
        if (!this.options.renderFollowups) {
            return;
        }
        this.followupsDisposables.clear();
        clearNode(this.followupsContainer);
        if (items && items.length > 0) {
            this.followupsDisposables.add(this.instantiationService.createInstance(ChatFollowups, this.followupsContainer, items, this.location, undefined, followup => this._onDidAcceptFollowup.fire({ followup, response })));
        }
    }
    layout(height, width) {
        this.cachedDimensions = new Dimension(width, height);
        return this._layout(height, width);
    }
    _layout(height, width, allowRecurse = true) {
        const followupsHeight = this.followupsContainer.offsetHeight;
        const inputPartBorder = 0;
        const inputPartHorizontalPadding = this.options.renderStyle === 'compact' ? 8 : 40;
        const inputPartVerticalPadding = this.options.renderStyle === 'compact' ? 12 : 24;
        const inputEditorHeight = Math.min(this._inputEditor.getContentHeight(), height - followupsHeight - inputPartVerticalPadding - inputPartBorder, INPUT_EDITOR_MAX_HEIGHT);
        const implicitContextHeight = this.implicitContextContainer.offsetHeight;
        const inputEditorBorder = 2;
        this._inputPartHeight = followupsHeight + inputEditorHeight + inputPartVerticalPadding + inputPartBorder + inputEditorBorder + implicitContextHeight;
        const editorBorder = 2;
        const editorPadding = 12;
        const executeToolbarWidth = this.cachedToolbarWidth = this.toolbar.getItemsWidth();
        const toolbarPadding = 4;
        const sideToolbarWidth = this.inputSideToolbarContainer ? getTotalWidth(this.inputSideToolbarContainer) + 4  : 0;
        const initialEditorScrollWidth = this._inputEditor.getScrollWidth();
        const newEditorWidth = width - inputPartHorizontalPadding - editorBorder - editorPadding - executeToolbarWidth - sideToolbarWidth - toolbarPadding;
        const newDimension = { width: newEditorWidth, height: inputEditorHeight };
        if (!this.previousInputEditorDimension || (this.previousInputEditorDimension.width !== newDimension.width || this.previousInputEditorDimension.height !== newDimension.height)) {
            this._inputEditor.layout(newDimension);
            this.previousInputEditorDimension = newDimension;
        }
        if (allowRecurse && initialEditorScrollWidth < 10) {
            return this._layout(height, width, false);
        }
    }
    saveState() {
        const inputHistory = this.history.getHistory();
        this.historyService.saveHistory(this.providerId, inputHistory);
    }
};
ChatInputPart = ChatInputPart_1 = ( __decorate([
    ( __param(2, IChatWidgetHistoryService)),
    ( __param(3, IModelService)),
    ( __param(4, IInstantiationService)),
    ( __param(5, IContextKeyService)),
    ( __param(6, IConfigurationService)),
    ( __param(7, IKeybindingService)),
    ( __param(8, IAccessibilityService))
], ChatInputPart));
function getLastPosition(model) {
    return { lineNumber: model.getLineCount(), column: model.getLineLength(model.getLineCount()) + 1 };
}
let ChatSubmitDropdownActionItem = class ChatSubmitDropdownActionItem extends DropdownWithPrimaryActionViewItem {
    constructor(action, dropdownAction, menuService, contextMenuService, chatAgentService, contextKeyService, keybindingService, notificationService, themeService, accessibilityService) {
        super(action, dropdownAction, [], '', contextMenuService, {
            getKeyBinding: (action) => keybindingService.lookupKeybinding(action.id, contextKeyService)
        }, keybindingService, notificationService, contextKeyService, themeService, accessibilityService);
        const menu = menuService.createMenu(MenuId.ChatExecuteSecondary, contextKeyService);
        const setActions = () => {
            const secondary = [];
            createAndFillInActionBarActions(menu, { shouldForwardArgs: true }, secondary);
            const secondaryAgent = chatAgentService.getSecondaryAgent();
            if (secondaryAgent) {
                secondary.forEach(a => {
                    if (a.id === ChatSubmitSecondaryAgentEditorAction.ID) {
                        a.label = ( localizeWithPath(
                            'vs/workbench/contrib/chat/browser/chatInputPart',
                            'chat.submitToSecondaryAgent',
                            "Send to @{0}",
                            secondaryAgent.name
                        ));
                    }
                    return a;
                });
            }
            this.update(dropdownAction, secondary);
        };
        setActions();
        this._register(menu.onDidChange(() => setActions()));
    }
};
ChatSubmitDropdownActionItem = ( __decorate([
    ( __param(2, IMenuService)),
    ( __param(3, IContextMenuService)),
    ( __param(4, IChatAgentService)),
    ( __param(5, IContextKeyService)),
    ( __param(6, IKeybindingService)),
    ( __param(7, INotificationService)),
    ( __param(8, IThemeService)),
    ( __param(9, IAccessibilityService))
], ChatSubmitDropdownActionItem));
export { ChatInputPart };
