import { renderMarkdownAsPlaintext } from '../../../../../base/browser/markdownRenderer.js';
import { localizeWithPath } from '../../../../../nls.js';
import { getMarkdownHeadersInCell } from './foldingModel.js';
import { OutlineEntry } from './OutlineEntry.js';
import { CellKind } from '../../common/notebookCommon.js';
class NotebookOutlineEntryFactory {
    constructor(executionStateService) {
        this.executionStateService = executionStateService;
        this.cellOutlineEntryCache = {};
    }
    getOutlineEntries(cell, target, index) {
        const entries = [];
        const isMarkdown = cell.cellKind === CellKind.Markup;
        let content = getCellFirstNonEmptyLine(cell);
        let hasHeader = false;
        if (isMarkdown) {
            const fullContent = cell.getText().substring(0, 10000);
            for (const { depth, text } of getMarkdownHeadersInCell(fullContent)) {
                hasHeader = true;
                entries.push(( new OutlineEntry(index++, depth, cell, text, false, false)));
            }
            if (!hasHeader) {
                const match = fullContent.match(/<h([1-6]).*>(.*)<\/h\1>/i);
                if (match) {
                    hasHeader = true;
                    const level = parseInt(match[1]);
                    const text = match[2].trim();
                    entries.push(( new OutlineEntry(index++, level, cell, text, false, false)));
                }
            }
            if (!hasHeader) {
                content = renderMarkdownAsPlaintext({ value: content });
            }
        }
        if (!hasHeader) {
            const exeState = !isMarkdown && this.executionStateService.getCellExecution(cell.uri);
            let preview = content.trim();
            if (!isMarkdown && cell.model.textModel) {
                const cachedEntries = this.cellOutlineEntryCache[cell.model.textModel.id];
                if (cachedEntries) {
                    if (target === 1 ) {
                        entries.push(( new OutlineEntry(
                            index++,
                            7,
                            cell,
                            preview,
                            !!exeState,
                            exeState ? exeState.isPaused : false
                        )));
                    }
                    cachedEntries.forEach((cached) => {
                        entries.push(( new OutlineEntry(
                            index++,
                            cached.level,
                            cell,
                            cached.name,
                            false,
                            false,
                            cached.range,
                            cached.kind
                        )));
                    });
                }
            }
            if (entries.length === 0) {
                if (preview.length === 0) {
                    preview = ( localizeWithPath(
                        'vs/workbench/contrib/notebook/browser/viewModel/notebookOutlineEntryFactory',
                        'empty',
                        "empty cell"
                    ));
                }
                entries.push(( new OutlineEntry(
                    index++,
                    7,
                    cell,
                    preview,
                    !!exeState,
                    exeState ? exeState.isPaused : false
                )));
            }
        }
        return entries;
    }
    async cacheSymbols(cell, outlineModelService, cancelToken) {
        const textModel = await cell.resolveTextModel();
        const outlineModel = await outlineModelService.getOrCreate(textModel, cancelToken);
        const entries = createOutlineEntries(outlineModel.getTopLevelSymbols(), 8);
        this.cellOutlineEntryCache[textModel.id] = entries;
    }
}
function createOutlineEntries(symbols, level) {
    const entries = [];
    symbols.forEach(symbol => {
        entries.push({ name: symbol.name, range: symbol.range, level, kind: symbol.kind });
        if (symbol.children) {
            entries.push(...createOutlineEntries(symbol.children, level + 1));
        }
    });
    return entries;
}
function getCellFirstNonEmptyLine(cell) {
    const textBuffer = cell.textBuffer;
    for (let i = 0; i < textBuffer.getLineCount(); i++) {
        const firstNonWhitespace = textBuffer.getLineFirstNonWhitespaceColumn(i + 1);
        const lineLength = textBuffer.getLineLength(i + 1);
        if (firstNonWhitespace < lineLength) {
            return textBuffer.getLineContent(i + 1);
        }
    }
    return cell.getText().substring(0, 100);
}
export { NotebookOutlineEntryFactory };
