import { __decorate, __param } from '../../../../../../../external/tslib/tslib.es6.js';
import { addDisposableListener, Dimension } from '../../../../base/browser/dom.js';
import { status } from '../../../../base/browser/ui/aria/aria.js';
import { toDisposable } from '../../../../base/common/lifecycle.js';
import { assertType } from '../../../../base/common/types.js';
import { EditorOption } from '../../../../editor/common/config/editorOptions.js';
import { ZoneWidget } from '../../../../editor/contrib/zoneWidget/browser/zoneWidget.js';
import { localizeWithPath } from '../../../../nls.js';
import { IContextKeyService } from '../../../../platform/contextkey/common/contextkey.service.js';
import { IInstantiationService } from '../../../../platform/instantiation/common/instantiation.js';
import { CTX_INLINE_CHAT_OUTER_CURSOR_POSITION, MENU_INLINE_CHAT_WIDGET_STATUS, ACTION_REGENERATE_RESPONSE, ACTION_TOGGLE_DIFF, ACTION_ACCEPT_CHANGES, MENU_INLINE_CHAT_EXECUTE, InlineChatConfigKeys, EditMode } from '../common/inlineChat.js';
import { EditorBasedInlineChatWidget } from './inlineChatWidget.js';
import { isEqual } from '../../../../base/common/resources.js';
import { StableEditorBottomScrollState } from '../../../../editor/browser/stableEditorScroll.js';
import { ScrollType } from '../../../../editor/common/editorCommon.js';
import { IConfigurationService } from '../../../../platform/configuration/common/configuration.service.js';
import { ILogService } from '../../../../platform/log/common/log.service.js';
const _moduleId = "vs/workbench/contrib/inlineChat/browser/inlineChatZoneWidget";
let InlineChatZoneWidget = class InlineChatZoneWidget extends ZoneWidget {
    constructor(location, editor, _instaService, _logService, contextKeyService, configurationService) {
        super(editor, { showFrame: false, showArrow: false, isAccessible: true, className: 'inline-chat-widget', keepEditorSelection: true, showInHiddenAreas: true, ordinal: 10000 });
        this._instaService = _instaService;
        this._logService = _logService;
        this._ctxCursorPosition = CTX_INLINE_CHAT_OUTER_CURSOR_POSITION.bindTo(contextKeyService);
        this._disposables.add(toDisposable(() => {
            this._ctxCursorPosition.reset();
        }));
        this.widget = this._instaService.createInstance(EditorBasedInlineChatWidget, location, this.editor, {
            statusMenuId: {
                menu: MENU_INLINE_CHAT_WIDGET_STATUS,
                options: {
                    buttonConfigProvider: action => {
                        if (( (( (new Set([ACTION_REGENERATE_RESPONSE, ACTION_TOGGLE_DIFF]))).has(action.id)))) {
                            return { isSecondary: true, showIcon: true, showLabel: false };
                        }
                        else if (action.id === ACTION_ACCEPT_CHANGES) {
                            return { isSecondary: false };
                        }
                        else {
                            return { isSecondary: true };
                        }
                    }
                }
            },
            chatWidgetViewOptions: {
                menus: {
                    executeToolbar: MENU_INLINE_CHAT_EXECUTE,
                    telemetrySource: 'interactiveEditorWidget-toolbar',
                },
                rendererOptions: {
                    renderTextEditsAsSummary: (uri) => {
                        return isEqual(uri, editor.getModel()?.uri)
                            && configurationService.getValue(InlineChatConfigKeys.Mode) === EditMode.Live;
                    },
                }
            }
        });
        this._disposables.add(this.widget);
        let scrollState;
        this._disposables.add(this.widget.chatWidget.onWillMaybeChangeHeight(() => {
            if (this.position) {
                scrollState = StableEditorBottomScrollState.capture(this.editor);
            }
        }));
        this._disposables.add(this.widget.onDidChangeHeight(() => {
            if (this.position) {
                scrollState ??= StableEditorBottomScrollState.capture(this.editor);
                const height = this._computeHeight();
                this._relayout(height.linesValue);
                scrollState.restore(this.editor);
                scrollState = undefined;
                this._revealTopOfZoneWidget(this.position, height);
            }
        }));
        this.create();
        this._disposables.add(addDisposableListener(this.domNode, 'click', e => {
            if (!this.editor.hasWidgetFocus() && !this.widget.hasFocus()) {
                this.editor.focus();
            }
        }, true));
        const updateCursorIsAboveContextKey = () => {
            if (!this.position || !this.editor.hasModel()) {
                this._ctxCursorPosition.reset();
            }
            else if (this.position.lineNumber === this.editor.getPosition().lineNumber) {
                this._ctxCursorPosition.set('above');
            }
            else if (this.position.lineNumber + 1 === this.editor.getPosition().lineNumber) {
                this._ctxCursorPosition.set('below');
            }
            else {
                this._ctxCursorPosition.reset();
            }
        };
        this._disposables.add(this.editor.onDidChangeCursorPosition(e => updateCursorIsAboveContextKey()));
        this._disposables.add(this.editor.onDidFocusEditorText(e => updateCursorIsAboveContextKey()));
        updateCursorIsAboveContextKey();
    }
    _fillContainer(container) {
        container.appendChild(this.widget.domNode);
    }
    _doLayout(heightInPixel) {
        const info = this.editor.getLayoutInfo();
        let width = info.contentWidth - (info.glyphMarginWidth + info.decorationsWidth);
        width = Math.min(640, width);
        this._dimension = ( (new Dimension(width, heightInPixel)));
        this.widget.layout(this._dimension);
    }
    _computeHeight() {
        const chatContentHeight = this.widget.contentHeight;
        const editorHeight = this.editor.getLayoutInfo().height;
        const contentHeight = Math.min(chatContentHeight, Math.max(this.widget.minHeight, editorHeight * 0.42));
        const heightInLines = contentHeight / this.editor.getOption(EditorOption.lineHeight);
        return { linesValue: heightInLines, pixelsValue: contentHeight };
    }
    _onWidth(_widthInPixel) {
        if (this._dimension) {
            this._doLayout(this._dimension.height);
        }
    }
    show(position) {
        assertType(this.container);
        const scrollState = StableEditorBottomScrollState.capture(this.editor);
        const info = this.editor.getLayoutInfo();
        const marginWithoutIndentation = info.glyphMarginWidth + info.decorationsWidth + info.lineNumbersWidth;
        this.container.style.marginLeft = `${marginWithoutIndentation}px`;
        const height = this._computeHeight();
        super.show(position, height.linesValue);
        this.widget.chatWidget.setVisible(true);
        this.widget.focus();
        scrollState.restore(this.editor);
        this._revealTopOfZoneWidget(position, height);
    }
    updatePositionAndHeight(position) {
        const scrollState = StableEditorBottomScrollState.capture(this.editor);
        const height = this._computeHeight();
        super.updatePositionAndHeight(position, height.linesValue);
        scrollState.restore(this.editor);
        this._revealTopOfZoneWidget(position, height);
    }
    _revealTopOfZoneWidget(position, height) {
        const lineNumber = position.lineNumber <= 1 ? 1 : 1 + position.lineNumber;
        const scrollTop = this.editor.getScrollTop();
        const lineTop = this.editor.getTopForLineNumber(lineNumber);
        const zoneTop = lineTop - height.pixelsValue;
        const editorHeight = this.editor.getLayoutInfo().height;
        const lineBottom = this.editor.getBottomForLineNumber(lineNumber);
        let newScrollTop = zoneTop;
        let forceScrollTop = false;
        if (lineBottom >= (scrollTop + editorHeight)) {
            newScrollTop = lineBottom - editorHeight;
            forceScrollTop = true;
        }
        if (newScrollTop < scrollTop || forceScrollTop) {
            this._logService.trace('[IE] REVEAL zone', { zoneTop, lineTop, lineBottom, scrollTop, newScrollTop, forceScrollTop });
            this.editor.setScrollTop(newScrollTop, ScrollType.Immediate);
        }
    }
    revealRange(range, isLastLine) {
    }
    _getWidth(info) {
        return info.width - info.minimap.minimapWidth;
    }
    hide() {
        const scrollState = StableEditorBottomScrollState.capture(this.editor);
        this._ctxCursorPosition.reset();
        this.widget.reset();
        this.widget.chatWidget.setVisible(false);
        super.hide();
        status(( localizeWithPath(_moduleId, 0, 'Closed inline chat widget')));
        scrollState.restore(this.editor);
    }
};
InlineChatZoneWidget = ( (__decorate([
    ( (__param(2, IInstantiationService))),
    ( (__param(3, ILogService))),
    ( (__param(4, IContextKeyService))),
    ( (__param(5, IConfigurationService)))
], InlineChatZoneWidget)));
export { InlineChatZoneWidget };
