import { __decorate, __param } from '../../../../../../../external/tslib/tslib.es6.js';
import { append, $ as $$1 } from '../../../../base/browser/dom.js';
import { asArray } from '../../../../base/common/arrays.js';
import { AsyncIterableObject } from '../../../../base/common/async.js';
import { MarkdownString, isEmptyMarkdownString } from '../../../../base/common/htmlContent.js';
import { DisposableStore } from '../../../../base/common/lifecycle.js';
import { MarkdownRenderer } from '../../../browser/widget/markdownRenderer/browser/markdownRenderer.js';
import { Position } from '../../../common/core/position.js';
import { Range } from '../../../common/core/range.js';
import { ILanguageService } from '../../../common/languages/language.js';
import { getHover } from './getHover.js';
import { localizeWithPath } from '../../../../nls.js';
import { IConfigurationService } from '../../../../platform/configuration/common/configuration.service.js';
import { IOpenerService } from '../../../../platform/opener/common/opener.service.js';
import { ILanguageFeaturesService } from '../../../common/services/languageFeatures.js';
const _moduleId = "vs/editor/contrib/hover/browser/markdownHoverParticipant";
const $ = $$1;
class MarkdownHover {
    constructor(owner, range, contents, isBeforeContent, ordinal) {
        this.owner = owner;
        this.range = range;
        this.contents = contents;
        this.isBeforeContent = isBeforeContent;
        this.ordinal = ordinal;
    }
    isValidForHoverAnchor(anchor) {
        return (anchor.type === 1
            && this.range.startColumn <= anchor.range.startColumn
            && this.range.endColumn >= anchor.range.endColumn);
    }
}
let MarkdownHoverParticipant = class MarkdownHoverParticipant {
    constructor(_editor, _languageService, _openerService, _configurationService, _languageFeaturesService) {
        this._editor = _editor;
        this._languageService = _languageService;
        this._openerService = _openerService;
        this._configurationService = _configurationService;
        this._languageFeaturesService = _languageFeaturesService;
        this.hoverOrdinal = 3;
    }
    createLoadingMessage(anchor) {
        return (
             (new MarkdownHover(
                this,
                anchor.range,
                [( (new MarkdownString())).appendText(( localizeWithPath(_moduleId, 0, "Loading...")))],
                false,
                2000
            ))
        );
    }
    computeSync(anchor, lineDecorations) {
        if (!this._editor.hasModel() || anchor.type !== 1 ) {
            return [];
        }
        const model = this._editor.getModel();
        const lineNumber = anchor.range.startLineNumber;
        const maxColumn = model.getLineMaxColumn(lineNumber);
        const result = [];
        let index = 1000;
        const lineLength = model.getLineLength(lineNumber);
        const languageId = model.getLanguageIdAtPosition(anchor.range.startLineNumber, anchor.range.startColumn);
        const stopRenderingLineAfter = this._editor.getOption(117 );
        const maxTokenizationLineLength = this._configurationService.getValue('editor.maxTokenizationLineLength', {
            overrideIdentifier: languageId
        });
        let stopRenderingMessage = false;
        if (stopRenderingLineAfter >= 0 && lineLength > stopRenderingLineAfter && anchor.range.startColumn >= stopRenderingLineAfter) {
            stopRenderingMessage = true;
            result.push(( (new MarkdownHover(this, anchor.range, [{
                    value: ( localizeWithPath(
                        _moduleId,
                        1,
                        "Rendering paused for long line for performance reasons. This can be configured via `editor.stopRenderingLineAfter`."
                    ))
                }], false, index++))));
        }
        if (!stopRenderingMessage && typeof maxTokenizationLineLength === 'number' && lineLength >= maxTokenizationLineLength) {
            result.push(( (new MarkdownHover(this, anchor.range, [{
                    value: ( localizeWithPath(
                        _moduleId,
                        2,
                        "Tokenization is skipped for long lines for performance reasons. This can be configured via `editor.maxTokenizationLineLength`."
                    ))
                }], false, index++))));
        }
        let isBeforeContent = false;
        for (const d of lineDecorations) {
            const startColumn = (d.range.startLineNumber === lineNumber) ? d.range.startColumn : 1;
            const endColumn = (d.range.endLineNumber === lineNumber) ? d.range.endColumn : maxColumn;
            const hoverMessage = d.options.hoverMessage;
            if (!hoverMessage || isEmptyMarkdownString(hoverMessage)) {
                continue;
            }
            if (d.options.beforeContentClassName) {
                isBeforeContent = true;
            }
            const range = ( (new Range(
                anchor.range.startLineNumber,
                startColumn,
                anchor.range.startLineNumber,
                endColumn
            )));
            result.push(( (new MarkdownHover(this, range, asArray(hoverMessage), isBeforeContent, index++))));
        }
        return result;
    }
    computeAsync(anchor, lineDecorations, token) {
        if (!this._editor.hasModel() || anchor.type !== 1 ) {
            return AsyncIterableObject.EMPTY;
        }
        const model = this._editor.getModel();
        if (!( (this._languageFeaturesService.hoverProvider.has(model)))) {
            return AsyncIterableObject.EMPTY;
        }
        const position = ( (new Position(anchor.range.startLineNumber, anchor.range.startColumn)));
        return (
             (getHover(this._languageFeaturesService.hoverProvider, model, position, token)
                .filter(item => !isEmptyMarkdownString(item.hover.contents))
                .map(item => {
                const rng = item.hover.range ? Range.lift(item.hover.range) : anchor.range;
                return (
                     (new MarkdownHover(this, rng, item.hover.contents, false, item.ordinal))
                );
            }))
        );
    }
    renderHoverParts(context, hoverParts) {
        return renderMarkdownHovers(context, hoverParts, this._editor, this._languageService, this._openerService);
    }
};
MarkdownHoverParticipant = ( (__decorate([
    ( (__param(1, ILanguageService))),
    ( (__param(2, IOpenerService))),
    ( (__param(3, IConfigurationService))),
    ( (__param(4, ILanguageFeaturesService)))
], MarkdownHoverParticipant)));
function renderMarkdownHovers(context, hoverParts, editor, languageService, openerService) {
    hoverParts.sort((a, b) => a.ordinal - b.ordinal);
    const disposables = ( (new DisposableStore()));
    for (const hoverPart of hoverParts) {
        for (const contents of hoverPart.contents) {
            if (isEmptyMarkdownString(contents)) {
                continue;
            }
            const markdownHoverElement = $('div.hover-row.markdown-hover');
            const hoverContentsElement = append(markdownHoverElement, $('div.hover-contents'));
            const renderer = disposables.add(( (new MarkdownRenderer({ editor }, languageService, openerService))));
            disposables.add(renderer.onDidRenderAsync(() => {
                hoverContentsElement.className = 'hover-contents code-hover-contents';
                context.onContentsChanged();
            }));
            const renderedContents = disposables.add(renderer.render(contents));
            hoverContentsElement.appendChild(renderedContents.element);
            context.fragment.appendChild(markdownHoverElement);
        }
    }
    return disposables;
}
export { MarkdownHover, MarkdownHoverParticipant, renderMarkdownHovers };
