"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getHoverInformation = void 0;
const graphql_1 = require("graphql");
const getAutocompleteSuggestions_1 = require("./getAutocompleteSuggestions");
function getHoverInformation(schema, queryText, cursor, contextToken, config) {
    const token = contextToken || (0, getAutocompleteSuggestions_1.getTokenAtPosition)(queryText, cursor);
    if (!schema || !token || !token.state) {
        return '';
    }
    const { kind, step } = token.state;
    const typeInfo = (0, getAutocompleteSuggestions_1.getTypeInfo)(schema, token.state);
    const options = Object.assign(Object.assign({}, config), { schema });
    if ((kind === 'Field' && step === 0 && typeInfo.fieldDef) ||
        (kind === 'AliasedField' && step === 2 && typeInfo.fieldDef)) {
        const into = [];
        renderMdCodeStart(into, options);
        renderField(into, typeInfo, options);
        renderMdCodeEnd(into, options);
        renderDescription(into, options, typeInfo.fieldDef);
        return into.join('').trim();
    }
    if (kind === 'Directive' && step === 1 && typeInfo.directiveDef) {
        const into = [];
        renderMdCodeStart(into, options);
        renderDirective(into, typeInfo, options);
        renderMdCodeEnd(into, options);
        renderDescription(into, options, typeInfo.directiveDef);
        return into.join('').trim();
    }
    if (kind === 'Argument' && step === 0 && typeInfo.argDef) {
        const into = [];
        renderMdCodeStart(into, options);
        renderArg(into, typeInfo, options);
        renderMdCodeEnd(into, options);
        renderDescription(into, options, typeInfo.argDef);
        return into.join('').trim();
    }
    if (kind === 'EnumValue' &&
        typeInfo.enumValue &&
        'description' in typeInfo.enumValue) {
        const into = [];
        renderMdCodeStart(into, options);
        renderEnumValue(into, typeInfo, options);
        renderMdCodeEnd(into, options);
        renderDescription(into, options, typeInfo.enumValue);
        return into.join('').trim();
    }
    if (kind === 'NamedType' && typeInfo.type && 'description' in typeInfo.type) {
        const into = [];
        renderMdCodeStart(into, options);
        renderType(into, typeInfo, options, typeInfo.type);
        renderMdCodeEnd(into, options);
        renderDescription(into, options, typeInfo.type);
        return into.join('').trim();
    }
    return '';
}
exports.getHoverInformation = getHoverInformation;
function renderMdCodeStart(into, options) {
    if (options.useMarkdown) {
        text(into, '```graphql\n');
    }
}
function renderMdCodeEnd(into, options) {
    if (options.useMarkdown) {
        text(into, '\n```');
    }
}
function renderField(into, typeInfo, options) {
    renderQualifiedField(into, typeInfo, options);
    renderTypeAnnotation(into, typeInfo, options, typeInfo.type);
}
function renderQualifiedField(into, typeInfo, options) {
    if (!typeInfo.fieldDef) {
        return;
    }
    const fieldName = typeInfo.fieldDef.name;
    if (fieldName.slice(0, 2) !== '__') {
        renderType(into, typeInfo, options, typeInfo.parentType);
        text(into, '.');
    }
    text(into, fieldName);
}
function renderDirective(into, typeInfo, _options) {
    if (!typeInfo.directiveDef) {
        return;
    }
    const name = '@' + typeInfo.directiveDef.name;
    text(into, name);
}
function renderArg(into, typeInfo, options) {
    if (typeInfo.directiveDef) {
        renderDirective(into, typeInfo, options);
    }
    else if (typeInfo.fieldDef) {
        renderQualifiedField(into, typeInfo, options);
    }
    if (!typeInfo.argDef) {
        return;
    }
    const { name } = typeInfo.argDef;
    text(into, '(');
    text(into, name);
    renderTypeAnnotation(into, typeInfo, options, typeInfo.inputType);
    text(into, ')');
}
function renderTypeAnnotation(into, typeInfo, options, t) {
    text(into, ': ');
    renderType(into, typeInfo, options, t);
}
function renderEnumValue(into, typeInfo, options) {
    if (!typeInfo.enumValue) {
        return;
    }
    const { name } = typeInfo.enumValue;
    renderType(into, typeInfo, options, typeInfo.inputType);
    text(into, '.');
    text(into, name);
}
function renderType(into, typeInfo, options, t) {
    if (!t) {
        return;
    }
    if (t instanceof graphql_1.GraphQLNonNull) {
        renderType(into, typeInfo, options, t.ofType);
        text(into, '!');
    }
    else if (t instanceof graphql_1.GraphQLList) {
        text(into, '[');
        renderType(into, typeInfo, options, t.ofType);
        text(into, ']');
    }
    else {
        text(into, t.name);
    }
}
function renderDescription(into, options, def) {
    if (!def) {
        return;
    }
    const description = typeof def.description === 'string' ? def.description : null;
    if (description) {
        text(into, '\n\n');
        text(into, description);
    }
    renderDeprecation(into, options, def);
}
function renderDeprecation(into, _options, def) {
    if (!def) {
        return;
    }
    const reason = def.deprecationReason || null;
    if (!reason) {
        return;
    }
    text(into, '\n\n');
    text(into, 'Deprecated: ');
    text(into, reason);
}
function text(into, content) {
    into.push(content);
}
//# sourceMappingURL=getHoverInformation.js.map