
import { __decorate, __param } from '../../../../../../../../external/tslib/tslib.es6.js';
import { localize, localize2 } from '../../../../../nls.js';
import { ItemActivation } from '../../../../../platform/quickinput/common/quickInput.js';
import { IQuickInputService } from '../../../../../platform/quickinput/common/quickInput.service.js';
import { SIDE_GROUP } from '../../../../services/editor/common/editorService.js';
import { IEditorService } from '../../../../services/editor/common/editorService.service.js';
import { Registry } from '../../../../../platform/registry/common/platform.js';
import { Extensions } from '../../../../../platform/quickinput/common/quickAccess.js';
import { AbstractGotoSymbolQuickAccessProvider } from '../../../../../editor/contrib/quickAccess/browser/gotoSymbolQuickAccess.js';
import { IConfigurationService } from '../../../../../platform/configuration/common/configuration.service.js';
import { Disposable, DisposableStore, toDisposable, MutableDisposable } from '../../../../../base/common/lifecycle.js';
import { timeout } from '../../../../../base/common/async.js';
import { CancellationTokenSource } from '../../../../../base/common/cancellation.js';
import { Action2, MenuId, registerAction2 } from '../../../../../platform/actions/common/actions.js';
import { KeyMod as KeyMod$1, KeyCode } from '../../../../../base/common/keyCodes.js';
import { prepareQuery } from '../../../../../base/common/fuzzyScorer.js';
import { SymbolKind } from '../../../../../editor/common/languages.js';
import { fuzzyScore } from '../../../../../base/common/filters.js';
import { onUnexpectedError } from '../../../../../base/common/errors.js';
import { KeybindingWeight } from '../../../../../platform/keybinding/common/keybindingsRegistry.js';
import { OutlineTarget } from '../../../../services/outline/browser/outline.js';
import { IOutlineService } from '../../../../services/outline/browser/outline.service.js';
import { isCompositeEditor } from '../../../../../editor/browser/editorBrowser.js';
import { IOutlineModelService } from '../../../../../editor/contrib/documentSymbols/browser/outlineModel.service.js';
import { ILanguageFeaturesService } from '../../../../../editor/common/services/languageFeatures.service.js';
import { ContextKeyExpr } from '../../../../../platform/contextkey/common/contextkey.js';
import { accessibleViewIsShown, accessibilityHelpIsShown } from '../../../accessibility/browser/accessibilityConfiguration.js';
import { parseLabelWithIcons, matchesFuzzyIconAware } from '../../../../../base/common/iconLabels.js';
import { IChatWidgetService } from '../../../chat/browser/chat.service.js';

var GotoSymbolQuickAccessProvider_1;
let GotoSymbolQuickAccessProvider = class GotoSymbolQuickAccessProvider extends AbstractGotoSymbolQuickAccessProvider {
    static {
        GotoSymbolQuickAccessProvider_1 = this;
    }
    constructor(
        editorService,
        configurationService,
        languageFeaturesService,
        outlineService,
        outlineModelService,
        chatWidgetService
    ) {
        super(languageFeaturesService, outlineModelService, {
            openSideBySideDirection: () => this.configuration.openSideBySideDirection
        });
        this.editorService = editorService;
        this.configurationService = configurationService;
        this.outlineService = outlineService;
        this.chatWidgetService = chatWidgetService;
        this.onDidActiveTextEditorControlChange = this.editorService.onDidActiveEditorChange;
    }
    get configuration() {
        const editorConfig = this.configurationService.getValue().workbench?.editor;
        return {
            openEditorPinned: !editorConfig?.enablePreviewFromQuickOpen || !editorConfig?.enablePreview,
            openSideBySideDirection: editorConfig?.openSideBySideDirection
        };
    }
    get activeTextEditorControl() {
        if (isCompositeEditor(this.editorService.activeEditorPane?.getControl())) {
            return undefined;
        }
        return this.editorService.activeTextEditorControl;
    }
    gotoLocation(context, options) {
        if ((options.keyMods.alt || (this.configuration.openEditorPinned && options.keyMods.ctrlCmd) || options.forceSideBySide) && this.editorService.activeEditor) {
            context.restoreViewState?.();
            const editorOptions = {
                selection: options.range,
                pinned: options.keyMods.ctrlCmd || this.configuration.openEditorPinned,
                preserveFocus: options.preserveFocus
            };
            this.editorService.openEditor(this.editorService.activeEditor, editorOptions, SIDE_GROUP);
        }
        else {
            super.gotoLocation(context, options);
        }
    }
    static {
        this.SYMBOL_PICKS_TIMEOUT = 8000;
    }
    async getSymbolPicks(model, filter, options, disposables, token) {
        const result = await Promise.race([
            this.waitForLanguageSymbolRegistry(model, disposables),
            timeout(GotoSymbolQuickAccessProvider_1.SYMBOL_PICKS_TIMEOUT)
        ]);
        if (!result || token.isCancellationRequested) {
            return [];
        }
        return this.doGetSymbolPicks(
            this.getDocumentSymbols(model, token),
            prepareQuery(filter),
            options,
            token,
            model
        );
    }
    async doGetSymbolPicks(symbolsPromise, query, options, token, model) {
        const picks = await super.doGetSymbolPicks(symbolsPromise, query, options, token, model);
        const modelUri = model.uri;
        for (const pick of picks) {
            const symbolPick = pick;
            if (symbolPick.range && !symbolPick.attach) {
                symbolPick.attach = () => {
                    const widget = this.chatWidgetService.lastFocusedWidget;
                    if (!widget) {
                        return;
                    }
                    const entry = {
                        kind: "symbol",
                        id: JSON.stringify({
                            uri: ( modelUri.toString()),
                            range: symbolPick.range.decoration
                        }),
                        name: symbolPick.symbolName ?? symbolPick.label,
                        value: {
                            uri: modelUri,
                            range: symbolPick.range.decoration
                        },
                        symbolKind: symbolPick.kind
                    };
                    widget.attachmentModel.addContext(entry);
                };
            }
        }
        return picks;
    }
    provideWithoutTextEditor(picker) {
        if (this.canPickWithOutlineService()) {
            return this.doGetOutlinePicks(picker);
        }
        return super.provideWithoutTextEditor(picker);
    }
    canPickWithOutlineService() {
        return this.editorService.activeEditorPane ? this.outlineService.canCreateOutline(this.editorService.activeEditorPane) : false;
    }
    doGetOutlinePicks(picker) {
        const pane = this.editorService.activeEditorPane;
        if (!pane) {
            return Disposable.None;
        }
        const cts = ( new CancellationTokenSource());
        const disposables = ( new DisposableStore());
        disposables.add(toDisposable(() => cts.dispose(true)));
        picker.busy = true;
        this.outlineService.createOutline(pane, OutlineTarget.QuickPick, cts.token).then(outline => {
            if (!outline) {
                return;
            }
            if (cts.token.isCancellationRequested) {
                outline.dispose();
                return;
            }
            disposables.add(outline);
            const viewState = outline.captureViewState();
            disposables.add(toDisposable(() => {
                if (picker.selectedItems.length === 0) {
                    viewState.dispose();
                }
            }));
            const entries = outline.config.quickPickDataSource.getQuickPickElements();
            const items = ( entries.map((entry, idx) => {
                return {
                    kind: SymbolKind.File,
                    index: idx,
                    score: 0,
                    label: entry.label,
                    description: entry.description,
                    ariaLabel: entry.ariaLabel,
                    iconClasses: entry.iconClasses
                };
            }));
            disposables.add(picker.onDidAccept(() => {
                picker.hide();
                const [entry] = picker.selectedItems;
                if (entry && entries[entry.index]) {
                    outline.reveal(entries[entry.index].element, {}, false, false);
                }
            }));
            const updatePickerItems = () => {
                const filteredItems = items.filter(item => {
                    if (picker.value === "@") {
                        item.score = 0;
                        item.highlights = undefined;
                        return true;
                    }
                    const trimmedQuery = picker.value.substring(AbstractGotoSymbolQuickAccessProvider.PREFIX.length).trim();
                    const parsedLabel = parseLabelWithIcons(item.label);
                    const score = fuzzyScore(
                        trimmedQuery,
                        trimmedQuery.toLowerCase(),
                        0,
                        parsedLabel.text,
                        parsedLabel.text.toLowerCase(),
                        0,
                        {
                            firstMatchCanBeWeak: true,
                            boostFullMatch: true
                        }
                    );
                    if (!score) {
                        return false;
                    }
                    item.score = score[1];
                    item.highlights = {
                        label: matchesFuzzyIconAware(trimmedQuery, parsedLabel) ?? undefined
                    };
                    return true;
                });
                if (filteredItems.length === 0) {
                    const label = ( localize(8474, "No matching entries"));
                    picker.items = [{
                        label,
                        index: -1,
                        kind: SymbolKind.String
                    }];
                    picker.ariaLabel = label;
                } else {
                    picker.items = filteredItems;
                }
            };
            updatePickerItems();
            disposables.add(picker.onDidChangeValue(updatePickerItems));
            const previewDisposable = ( new MutableDisposable());
            disposables.add(previewDisposable);
            disposables.add(picker.onDidChangeActive(() => {
                const [entry] = picker.activeItems;
                if (entry && entries[entry.index]) {
                    previewDisposable.value = outline.preview(entries[entry.index].element);
                } else {
                    previewDisposable.clear();
                }
            }));
        }).catch(err => {
            onUnexpectedError(err);
            picker.hide();
        }).finally(() => {
            picker.busy = false;
        });
        return disposables;
    }
};
GotoSymbolQuickAccessProvider = GotoSymbolQuickAccessProvider_1 = ( __decorate([( __param(0, IEditorService)), ( __param(1, IConfigurationService)), ( __param(2, ILanguageFeaturesService)), ( __param(3, IOutlineService)), ( __param(4, IOutlineModelService)), ( __param(5, IChatWidgetService))], GotoSymbolQuickAccessProvider));
class GotoSymbolAction extends Action2 {
    static {
        this.ID = "workbench.action.gotoSymbol";
    }
    constructor() {
        super({
            id: GotoSymbolAction.ID,
            title: {
                ...( localize2(8475, "Go to Symbol in Editor...")),
                mnemonicTitle: ( localize(8476, "Go to &&Symbol in Editor..."))
            },
            f1: true,
            keybinding: {
                when: ( ContextKeyExpr.and(( accessibleViewIsShown.negate()), ( accessibilityHelpIsShown.negate()))),
                weight: KeybindingWeight.WorkbenchContrib,
                primary: KeyMod$1.CtrlCmd | KeyMod$1.Shift | KeyCode.KeyO
            },
            menu: [{
                id: MenuId.MenubarGoMenu,
                group: "4_symbol_nav",
                order: 1
            }]
        });
    }
    run(accessor) {
        accessor.get(IQuickInputService).quickAccess.show(GotoSymbolQuickAccessProvider.PREFIX, {
            itemActivation: ItemActivation.NONE
        });
    }
}
registerAction2(GotoSymbolAction);
( Registry.as(Extensions.Quickaccess)).registerQuickAccessProvider({
    ctor: GotoSymbolQuickAccessProvider,
    prefix: AbstractGotoSymbolQuickAccessProvider.PREFIX,
    contextKey: "inFileSymbolsPicker",
    placeholder: ( localize(8477, "Type the name of a symbol to go to.")),
    helpEntries: [{
        description: ( localize(8478, "Go to Symbol in Editor")),
        prefix: AbstractGotoSymbolQuickAccessProvider.PREFIX,
        commandId: GotoSymbolAction.ID,
        commandCenterOrder: 40
    }, {
        description: ( localize(8479, "Go to Symbol in Editor by Category")),
        prefix: AbstractGotoSymbolQuickAccessProvider.PREFIX_BY_CATEGORY
    }]
});

export { GotoSymbolQuickAccessProvider };
