"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.doHover = void 0;
const vscode_languageserver_1 = require("vscode-languageserver");
const yaml_1 = require("yaml");
const ansible_1 = require("../utils/ansible");
const docsFormatter_1 = require("../utils/docsFormatter");
const misc_1 = require("../utils/misc");
const yaml_2 = require("../utils/yaml");
async function doHover(document, position, docsLibrary) {
    const yamlDocs = (0, yaml_2.parseAllDocuments)(document.getText());
    const path = (0, yaml_2.getPathAt)(document, position, yamlDocs);
    if (path) {
        const node = path[path.length - 1];
        if ((0, yaml_1.isScalar)(node) &&
            new yaml_2.AncestryBuilder(path).parentOfKey().get() // ensure we look at a key, not value of a Pair
        ) {
            if ((0, yaml_2.isPlayParam)(path)) {
                return getKeywordHover(document, node, ansible_1.playKeywords);
            }
            if ((0, yaml_2.isBlockParam)(path)) {
                return getKeywordHover(document, node, ansible_1.blockKeywords);
            }
            if ((0, yaml_2.isRoleParam)(path)) {
                return getKeywordHover(document, node, ansible_1.roleKeywords);
            }
            if ((0, yaml_2.isTaskParam)(path)) {
                if ((0, ansible_1.isTaskKeyword)(node.value)) {
                    return getKeywordHover(document, node, ansible_1.taskKeywords);
                }
                else {
                    const [module, hitFqcn] = await docsLibrary.findModule(node.value, path, document.uri);
                    const range = (0, yaml_2.getOrigRange)(node);
                    if (module && module.documentation) {
                        return {
                            contents: (0, docsFormatter_1.formatModule)(module.documentation, docsLibrary.getModuleRoute(hitFqcn || node.value)),
                            range: range ? (0, misc_1.toLspRange)(range, document) : undefined,
                        };
                    }
                    else if (hitFqcn) {
                        // check for tombstones
                        const route = docsLibrary.getModuleRoute(hitFqcn);
                        if (route) {
                            return {
                                contents: (0, docsFormatter_1.formatTombstone)(route),
                                range: range ? (0, misc_1.toLspRange)(range, document) : undefined,
                            };
                        }
                    }
                }
            }
            // hovering over a module option or sub-option
            const options = await (0, yaml_2.getPossibleOptionsForPath)(path, document, docsLibrary);
            if (options) {
                const option = options.get(node.value);
                if (option) {
                    return {
                        contents: (0, docsFormatter_1.formatOption)(option, true),
                    };
                }
            }
        }
    }
    return null;
}
exports.doHover = doHover;
function getKeywordHover(document, node, keywords) {
    const keywordDocumentation = keywords.get(node.value);
    const markupDoc = typeof keywordDocumentation === "string"
        ? {
            kind: vscode_languageserver_1.MarkupKind.Markdown,
            value: keywordDocumentation,
        }
        : keywordDocumentation;
    if (markupDoc) {
        const range = (0, yaml_2.getOrigRange)(node);
        return {
            contents: markupDoc,
            range: range ? (0, misc_1.toLspRange)(range, document) : undefined,
        };
    }
    else
        return null;
}
