"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.HoverProviderImpl = void 0;
const typescript_1 = __importDefault(require("typescript"));
const documents_1 = require("../../../lib/documents");
const previewer_1 = require("../previewer");
const utils_1 = require("../utils");
const utils_2 = require("./utils");
class HoverProviderImpl {
    constructor(lsAndTsDocResolver) {
        this.lsAndTsDocResolver = lsAndTsDocResolver;
    }
    async doHover(document, position) {
        const { lang, lsContainer, tsDoc, userPreferences } = await this.getLSAndTSDoc(document);
        const eventHoverInfo = this.getEventHoverInfo(lang, document, tsDoc, position);
        if (eventHoverInfo) {
            return eventHoverInfo;
        }
        const offset = tsDoc.offsetAt(tsDoc.getGeneratedPosition(position));
        const customElementDescription = this.getCustomElementDescription(lang, position, lsContainer, document, tsDoc);
        if (customElementDescription) {
            return {
                contents: {
                    value: customElementDescription,
                    kind: 'markdown'
                }
            };
        }
        const info = lang.getQuickInfoAtPosition(tsDoc.filePath, offset, userPreferences.maximumHoverLength);
        if (!info) {
            return null;
        }
        let declaration = typescript_1.default.displayPartsToString(info.displayParts);
        if (tsDoc.isSvelte5Plus &&
            declaration.includes('(alias)') &&
            declaration.includes('__sveltets_2_IsomorphicComponent')) {
            // info ends with "import ComponentName"
            declaration = declaration.substring(declaration.lastIndexOf('import'));
        }
        const documentation = (0, previewer_1.getMarkdownDocumentation)(info.documentation, info.tags);
        // https://microsoft.github.io/language-server-protocol/specification#textDocument_hover
        const contents = ['```typescript', declaration, '```']
            .concat(documentation ? ['---', documentation] : [])
            .join('\n');
        return (0, documents_1.mapObjWithRangeToOriginal)(tsDoc, {
            range: (0, utils_1.convertRange)(tsDoc, info.textSpan),
            contents
        });
    }
    getCustomElementDescription(lang, position, lsContainer, document, tsDoc) {
        const offset = document.offsetAt(position);
        const tag = (0, documents_1.getNodeIfIsInTagName)(document.html, offset);
        if (!tag || !tag.tag) {
            return;
        }
        return (0, utils_2.getCustomElementsDocument)(lang, lsContainer, tsDoc, tag.tag) ?? undefined;
    }
    getEventHoverInfo(lang, doc, tsDoc, originalPosition) {
        const possibleEventName = (0, documents_1.getWordAt)(doc.getText(), doc.offsetAt(originalPosition), {
            left: /\S+$/,
            right: /[\s=]/
        });
        if (!possibleEventName.startsWith('on:')) {
            return null;
        }
        const component = (0, utils_2.getComponentAtPosition)(lang, doc, tsDoc, originalPosition);
        if (!component) {
            return null;
        }
        const eventName = possibleEventName.substr('on:'.length);
        const event = component.getEvents().find((event) => event.name === eventName);
        if (!event) {
            return null;
        }
        return {
            contents: [
                '```typescript',
                `${event.name}: ${event.type}`,
                '```',
                event.doc || ''
            ].join('\n')
        };
    }
    async getLSAndTSDoc(document) {
        return this.lsAndTsDocResolver.getLSAndTSDoc(document);
    }
}
exports.HoverProviderImpl = HoverProviderImpl;
//# sourceMappingURL=HoverProvider.js.map