"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.MdDefinitionProvider = void 0;
const range_1 = require("../types/range");
const workspace_1 = require("../workspace");
const documentLinks_1 = require("./documentLinks");
class MdDefinitionProvider {
    #configuration;
    #workspace;
    #tocProvider;
    #linkCache;
    constructor(configuration, workspace, tocProvider, linkCache) {
        this.#configuration = configuration;
        this.#workspace = workspace;
        this.#tocProvider = tocProvider;
        this.#linkCache = linkCache;
    }
    async provideDefinition(document, position, token) {
        const toc = await this.#tocProvider.getForDocument(document);
        if (token.isCancellationRequested) {
            return [];
        }
        const header = toc.entries.find(entry => entry.line === position.line);
        if (header) {
            return header.headerLocation;
        }
        return this.#getDefinitionOfLinkAtPosition(document, position, token);
    }
    async #getDefinitionOfLinkAtPosition(document, position, token) {
        const docLinks = (await this.#linkCache.getForDocs([document]))[0];
        for (const link of docLinks) {
            if (link.kind === documentLinks_1.MdLinkKind.Definition && (0, range_1.rangeContains)(link.ref.range, position)) {
                return this.#getDefinitionOfRef(link.ref.text, docLinks);
            }
            if ((0, range_1.rangeContains)(link.source.hrefRange, position)) {
                return this.#getDefinitionOfLink(link, docLinks, token);
            }
        }
        return undefined;
    }
    async #getDefinitionOfLink(sourceLink, allLinksInFile, token) {
        if (sourceLink.href.kind === documentLinks_1.HrefKind.Reference) {
            return this.#getDefinitionOfRef(sourceLink.href.ref, allLinksInFile);
        }
        if (sourceLink.href.kind === documentLinks_1.HrefKind.External || !sourceLink.href.fragment) {
            return undefined;
        }
        const resolvedResource = await (0, workspace_1.statLinkToMarkdownFile)(this.#configuration, this.#workspace, sourceLink.href.path);
        if (!resolvedResource || token.isCancellationRequested) {
            return undefined;
        }
        const toc = await this.#tocProvider.get(resolvedResource);
        return toc.lookup(sourceLink.href.fragment)?.headerLocation;
    }
    #getDefinitionOfRef(ref, allLinksInFile) {
        const allDefinitions = new documentLinks_1.LinkDefinitionSet(allLinksInFile);
        const def = allDefinitions.lookup(ref);
        return def ? { range: def.source.range, uri: def.source.resource.toString() } : undefined;
    }
}
exports.MdDefinitionProvider = MdDefinitionProvider;
//# sourceMappingURL=definitions.js.map