import { __decorate, __param } from '../../../../../../../external/tslib/tslib.es6.js';
import './media/panel.css.js';
import { localizeWithPath } from '../../../../nls.js';
import { append, $, isActiveElement } from '../../../../base/browser/dom.js';
import { basename } from '../../../../base/common/resources.js';
import { IInstantiationService } from '../../../../platform/instantiation/common/instantiation.js';
import { IThemeService } from '../../../../platform/theme/common/themeService.service.js';
import { ResourceWithCommentThreads, CommentNode } from '../common/commentModel.js';
import { ICommentService } from './commentService.service.js';
import { IEditorService } from '../../../services/editor/common/editorService.service.js';
import { ResourceLabels } from '../../../browser/labels.js';
import { Filter, CommentsList, COMMENTS_VIEW_TITLE } from './commentsTreeViewer.js';
import { FilterViewPane } from '../../../browser/parts/views/viewPane.js';
import { IViewDescriptorService } from '../../../common/views.service.js';
import { IConfigurationService } from '../../../../platform/configuration/common/configuration.service.js';
import { RawContextKey } from '../../../../platform/contextkey/common/contextkey.js';
import { IContextKeyService } from '../../../../platform/contextkey/common/contextkey.service.js';
import { IContextMenuService } from '../../../../platform/contextview/browser/contextView.service.js';
import { IKeybindingService } from '../../../../platform/keybinding/common/keybinding.service.js';
import { IOpenerService } from '../../../../platform/opener/common/opener.service.js';
import { ITelemetryService } from '../../../../platform/telemetry/common/telemetry.service.js';
import { IUriIdentityService } from '../../../../platform/uriIdentity/common/uriIdentity.service.js';
import { CommentsViewFilterFocusContextKey } from './comments.js';
import { CommentsFilters } from './commentsViewActions.js';
import { Memento } from '../../../common/memento.js';
import { IStorageService } from '../../../../platform/storage/common/storage.service.js';
import { FilterOptions } from './commentsFilterOptions.js';
import { CommentThreadApplicability } from '../../../../editor/common/languages.js';
import { Iterable } from '../../../../base/common/iterator.js';
import { revealCommentThread } from './commentsController.js';
import { registerNavigableContainer } from '../../../browser/actions/widgetNavigationCommands.js';
import { CommentsModel } from './commentsModel.js';
const _moduleId = "vs/workbench/contrib/comments/browser/commentsView";
const CONTEXT_KEY_HAS_COMMENTS = ( (new RawContextKey('commentsView.hasComments', false)));
const CONTEXT_KEY_SOME_COMMENTS_EXPANDED = ( (new RawContextKey('commentsView.someCommentsExpanded', false)));
const VIEW_STORAGE_ID = 'commentsViewState';
function createResourceCommentsIterator(model) {
    return (
         (Iterable.map(model.resourceCommentThreads, m => {
            const CommentNodeIt = Iterable.from(m.commentThreads);
            const children = ( (Iterable.map(CommentNodeIt, r => ({ element: r }))));
            return { element: m, children };
        }))
    );
}
let CommentsPanel = class CommentsPanel extends FilterViewPane {
    constructor(options, instantiationService, viewDescriptorService, editorService, configurationService, contextKeyService, contextMenuService, keybindingService, openerService, themeService, commentService, telemetryService, uriIdentityService, storageService) {
        const stateMemento = ( (new Memento(VIEW_STORAGE_ID, storageService)));
        const viewState = stateMemento.getMemento(1 , 1 );
        super({
            ...options,
            filterOptions: {
                placeholder: ( localizeWithPath(_moduleId, 0, "Filter (e.g. text, author)")),
                ariaLabel: ( localizeWithPath(_moduleId, 1, "Filter comments")),
                history: viewState['filterHistory'] || [],
                text: viewState['filter'] || '',
                focusContextKey: CommentsViewFilterFocusContextKey.key
            }
        }, keybindingService, contextMenuService, configurationService, contextKeyService, viewDescriptorService, instantiationService, openerService, themeService, telemetryService);
        this.editorService = editorService;
        this.commentService = commentService;
        this.uriIdentityService = uriIdentityService;
        this.totalComments = 0;
        this.currentHeight = 0;
        this.currentWidth = 0;
        this.cachedFilterStats = undefined;
        this.onDidChangeVisibility = this.onDidChangeBodyVisibility;
        this.hasCommentsContextKey = CONTEXT_KEY_HAS_COMMENTS.bindTo(contextKeyService);
        this.someCommentsExpandedContextKey = CONTEXT_KEY_SOME_COMMENTS_EXPANDED.bindTo(contextKeyService);
        this.stateMemento = stateMemento;
        this.viewState = viewState;
        this.filters = this._register(( (new CommentsFilters({
            showResolved: this.viewState['showResolved'] !== false,
            showUnresolved: this.viewState['showUnresolved'] !== false,
        }, this.contextKeyService))));
        this.filter = ( (new Filter( (new FilterOptions(
            this.filterWidget.getFilterText(),
            this.filters.showResolved,
            this.filters.showUnresolved
        )))));
        this._register(this.filters.onDidChange((event) => {
            if (event.showResolved || event.showUnresolved) {
                this.updateFilter();
            }
        }));
        this._register(this.filterWidget.onDidChangeFilterText(() => this.updateFilter()));
    }
    saveState() {
        this.viewState['filter'] = this.filterWidget.getFilterText();
        this.viewState['filterHistory'] = this.filterWidget.getHistory();
        this.viewState['showResolved'] = this.filters.showResolved;
        this.viewState['showUnresolved'] = this.filters.showUnresolved;
        this.stateMemento.saveMemento();
        super.saveState();
    }
    render() {
        super.render();
        this._register(registerNavigableContainer({
            focusNotifiers: [this, this.filterWidget],
            focusNextWidget: () => {
                if (this.filterWidget.hasFocus()) {
                    this.focus();
                }
            },
            focusPreviousWidget: () => {
                if (!this.filterWidget.hasFocus()) {
                    this.focusFilter();
                }
            }
        }));
    }
    focusFilter() {
        this.filterWidget.focus();
    }
    clearFilterText() {
        this.filterWidget.setFilterText('');
    }
    getFilterStats() {
        if (!this.cachedFilterStats) {
            this.cachedFilterStats = {
                total: this.totalComments,
                filtered: this.tree?.getVisibleItemCount() ?? 0
            };
        }
        return this.cachedFilterStats;
    }
    updateFilter() {
        this.filter.options = ( (new FilterOptions(
            this.filterWidget.getFilterText(),
            this.filters.showResolved,
            this.filters.showUnresolved
        )));
        this.tree?.filterComments();
        this.cachedFilterStats = undefined;
        const { total, filtered } = this.getFilterStats();
        this.filterWidget.updateBadge(total === filtered || total === 0 ? undefined : ( localizeWithPath(_moduleId, 2, "Showing {0} of {1}", filtered, total)));
        this.filterWidget.checkMoreFilters(!this.filters.showResolved || !this.filters.showUnresolved);
    }
    renderBody(container) {
        super.renderBody(container);
        container.classList.add('comments-panel');
        const domContainer = append(container, $('.comments-panel-container'));
        this.treeContainer = append(domContainer, $('.tree-container'));
        this.treeContainer.classList.add('file-icon-themable-tree', 'show-file-icons');
        this.cachedFilterStats = undefined;
        this.createTree();
        this.createMessageBox(domContainer);
        this._register(this.commentService.onDidSetAllCommentThreads(this.onAllCommentsChanged, this));
        this._register(this.commentService.onDidUpdateCommentThreads(this.onCommentsUpdated, this));
        this._register(this.commentService.onDidDeleteDataProvider(this.onDataProviderDeleted, this));
        this._register(this.onDidChangeBodyVisibility(visible => {
            if (visible) {
                this.refresh();
            }
        }));
        this.renderComments();
    }
    focus() {
        super.focus();
        const element = this.tree?.getHTMLElement();
        if (element && isActiveElement(element)) {
            return;
        }
        if (!this.commentService.commentsModel.hasCommentThreads() && this.messageBoxContainer) {
            this.messageBoxContainer.focus();
        }
        else if (this.tree) {
            this.tree.domFocus();
        }
    }
    async renderComments() {
        this.treeContainer.classList.toggle('hidden', !this.commentService.commentsModel.hasCommentThreads());
        this.renderMessage();
        await this.tree?.setChildren(null, createResourceCommentsIterator(this.commentService.commentsModel));
    }
    collapseAll() {
        if (this.tree) {
            this.tree.collapseAll();
            this.tree.setSelection([]);
            this.tree.setFocus([]);
            this.tree.domFocus();
            this.tree.focusFirst();
        }
    }
    expandAll() {
        if (this.tree) {
            this.tree.expandAll();
            this.tree.setSelection([]);
            this.tree.setFocus([]);
            this.tree.domFocus();
            this.tree.focusFirst();
        }
    }
    get hasRendered() {
        return !!this.tree;
    }
    layoutBodyContent(height = this.currentHeight, width = this.currentWidth) {
        if (this.messageBoxContainer) {
            this.messageBoxContainer.style.height = `${height}px`;
        }
        this.tree?.layout(height, width);
        this.currentHeight = height;
        this.currentWidth = width;
    }
    createMessageBox(parent) {
        this.messageBoxContainer = append(parent, $('.message-box-container'));
        this.messageBoxContainer.setAttribute('tabIndex', '0');
    }
    renderMessage() {
        this.messageBoxContainer.textContent = this.commentService.commentsModel.getMessage();
        this.messageBoxContainer.classList.toggle('hidden', this.commentService.commentsModel.hasCommentThreads());
    }
    getAriaForNode(element) {
        if (element.range) {
            if (element.threadRelevance === CommentThreadApplicability.Outdated) {
                return ( localizeWithPath(
                    _moduleId,
                    3,
                    "Outdated from ${0} at line {1} column {2} in {3}, source: {4}",
                    element.comment.userName,
                    element.range.startLineNumber,
                    element.range.startColumn,
                    basename(element.resource),
                    (typeof element.comment.body === 'string') ? element.comment.body : element.comment.body.value
                ));
            }
            else {
                return ( localizeWithPath(
                    _moduleId,
                    4,
                    "${0} at line {1} column {2} in {3}, source: {4}",
                    element.comment.userName,
                    element.range.startLineNumber,
                    element.range.startColumn,
                    basename(element.resource),
                    (typeof element.comment.body === 'string') ? element.comment.body : element.comment.body.value
                ));
            }
        }
        else {
            if (element.threadRelevance === CommentThreadApplicability.Outdated) {
                return ( localizeWithPath(
                    _moduleId,
                    5,
                    "Outdated from {0} in {1}, source: {2}",
                    element.comment.userName,
                    basename(element.resource),
                    (typeof element.comment.body === 'string') ? element.comment.body : element.comment.body.value
                ));
            }
            else {
                return ( localizeWithPath(
                    _moduleId,
                    6,
                    "{0} in {1}, source: {2}",
                    element.comment.userName,
                    basename(element.resource),
                    (typeof element.comment.body === 'string') ? element.comment.body : element.comment.body.value
                ));
            }
        }
    }
    createTree() {
        this.treeLabels = this._register(this.instantiationService.createInstance(ResourceLabels, this));
        this.tree = this._register(this.instantiationService.createInstance(CommentsList, this.treeLabels, this.treeContainer, {
            overrideStyles: { listBackground: this.getBackgroundColor() },
            selectionNavigation: true,
            filter: this.filter,
            keyboardNavigationLabelProvider: {
                getKeyboardNavigationLabel: (item) => {
                    return undefined;
                }
            },
            accessibilityProvider: {
                getAriaLabel: (element) => {
                    if (element instanceof CommentsModel) {
                        return ( localizeWithPath(_moduleId, 7, "Comments for current workspace"));
                    }
                    if (element instanceof ResourceWithCommentThreads) {
                        return ( localizeWithPath(
                            _moduleId,
                            8,
                            "Comments in {0}, full path {1}",
                            basename(element.resource),
                            element.resource.fsPath
                        ));
                    }
                    if (element instanceof CommentNode) {
                        return this.getAriaForNode(element);
                    }
                    return '';
                },
                getWidgetAriaLabel() {
                    return COMMENTS_VIEW_TITLE.value;
                }
            }
        }));
        this._register(this.tree.onDidOpen(e => {
            this.openFile(e.element, e.editorOptions.pinned, e.editorOptions.preserveFocus, e.sideBySide);
        }));
        this._register(this.tree.onDidChangeModel(() => {
            this.updateSomeCommentsExpanded();
        }));
        this._register(this.tree.onDidChangeCollapseState(() => {
            this.updateSomeCommentsExpanded();
        }));
    }
    openFile(element, pinned, preserveFocus, sideBySide) {
        if (!element) {
            return;
        }
        if (!(element instanceof ResourceWithCommentThreads || element instanceof CommentNode)) {
            return;
        }
        const threadToReveal = element instanceof ResourceWithCommentThreads ? element.commentThreads[0].thread : element.thread;
        const commentToReveal = element instanceof ResourceWithCommentThreads ? element.commentThreads[0].comment : undefined;
        return revealCommentThread(this.commentService, this.editorService, this.uriIdentityService, threadToReveal, commentToReveal, false, pinned, preserveFocus, sideBySide);
    }
    async refresh() {
        if (!this.tree) {
            return;
        }
        if (this.isVisible()) {
            this.hasCommentsContextKey.set(this.commentService.commentsModel.hasCommentThreads());
            this.treeContainer.classList.toggle('hidden', !this.commentService.commentsModel.hasCommentThreads());
            this.cachedFilterStats = undefined;
            this.renderMessage();
            this.tree?.setChildren(null, createResourceCommentsIterator(this.commentService.commentsModel));
            if (this.tree.getSelection().length === 0 && this.commentService.commentsModel.hasCommentThreads()) {
                const firstComment = this.commentService.commentsModel.resourceCommentThreads[0].commentThreads[0];
                if (firstComment) {
                    this.tree.setFocus([firstComment]);
                    this.tree.setSelection([firstComment]);
                }
            }
        }
    }
    onAllCommentsChanged(e) {
        this.cachedFilterStats = undefined;
        this.totalComments += e.commentThreads.length;
        for (const thread of e.commentThreads) {
        }
        this.refresh();
    }
    onCommentsUpdated(e) {
        this.cachedFilterStats = undefined;
        this.totalComments += e.added.length;
        this.totalComments -= e.removed.length;
        for (const resource of this.commentService.commentsModel.resourceCommentThreads) {
            for (const thread of resource.commentThreads) {
            }
        }
        this.refresh();
    }
    onDataProviderDeleted(owner) {
        this.cachedFilterStats = undefined;
        this.totalComments = 0;
        this.refresh();
    }
    updateSomeCommentsExpanded() {
        this.someCommentsExpandedContextKey.set(this.isSomeCommentsExpanded());
    }
    areAllCommentsExpanded() {
        if (!this.tree) {
            return false;
        }
        const navigator = this.tree.navigate();
        while (navigator.next()) {
            if (this.tree.isCollapsed(navigator.current())) {
                return false;
            }
        }
        return true;
    }
    isSomeCommentsExpanded() {
        if (!this.tree) {
            return false;
        }
        const navigator = this.tree.navigate();
        while (navigator.next()) {
            if (!this.tree.isCollapsed(navigator.current())) {
                return true;
            }
        }
        return false;
    }
};
CommentsPanel = ( (__decorate([
    ( (__param(1, IInstantiationService))),
    ( (__param(2, IViewDescriptorService))),
    ( (__param(3, IEditorService))),
    ( (__param(4, IConfigurationService))),
    ( (__param(5, IContextKeyService))),
    ( (__param(6, IContextMenuService))),
    ( (__param(7, IKeybindingService))),
    ( (__param(8, IOpenerService))),
    ( (__param(9, IThemeService))),
    ( (__param(10, ICommentService))),
    ( (__param(11, ITelemetryService))),
    ( (__param(12, IUriIdentityService))),
    ( (__param(13, IStorageService)))
], CommentsPanel)));
export { CONTEXT_KEY_HAS_COMMENTS, CONTEXT_KEY_SOME_COMMENTS_EXPANDED, CommentsPanel };
