"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.hover = void 0;
const types_js_1 = require("../types.js");
const checker_js_1 = require("../checker.js");
const parser_js_1 = require("../parser.js");
const util_js_1 = require("./util.js");
const common_js_1 = require("./command/common.js");
function hover(doc, sourceFile, position) {
    const offset = doc.offsetAt(position);
    const g = sourceFile.graph;
    if (!g)
        return undefined;
    const node = (0, checker_js_1.findNodeAtOffset)(g, offset);
    if (node === undefined)
        return undefined;
    return getNodeHover(doc, sourceFile, node);
}
exports.hover = hover;
function getNodeHover(doc, sf, n) {
    const contents = getHoverContents(n);
    if (contents) {
        return {
            contents,
            range: (0, util_js_1.syntaxNodeToRange)(doc, sf, n),
        };
    }
    return undefined;
}
function getHoverContents(n) {
    if ((0, parser_js_1.isIdentifierNode)(n)) {
        const parent = n.parent;
        if (parent) {
            switch (parent.kind) {
                case types_js_1.SyntaxKind.NodeId:
                    return `(node) ${(0, checker_js_1.getIdentifierText)(n)}`;
                case types_js_1.SyntaxKind.Assignment: {
                    const assignment = parent;
                    const left = (0, checker_js_1.getIdentifierText)(assignment.leftId);
                    const right = (0, checker_js_1.getIdentifierText)(assignment.rightId);
                    return `(assignment) \`${left}\` = \`${right}\``;
                }
                case types_js_1.SyntaxKind.DirectedGraph:
                    return getGraphHover(parent);
                case types_js_1.SyntaxKind.UndirectedGraph:
                    return getGraphHover(parent);
                case types_js_1.SyntaxKind.SubGraphStatement: {
                    const sgs = parent;
                    const sg = sgs.subgraph;
                    return !!sg.id
                        ? `(sub graph) ${(0, checker_js_1.getIdentifierText)(sg.id)}`
                        : `(sub graph)`;
                }
                case types_js_1.SyntaxKind.SubGraph: {
                    const sg = parent;
                    return !!sg.id
                        ? `(sub graph) ${(0, checker_js_1.getIdentifierText)(sg.id)}`
                        : `(sub graph)`;
                }
                case types_js_1.SyntaxKind.IdEqualsIdStatement: {
                    const idEqId = parent;
                    const left = (0, checker_js_1.getIdentifierText)(idEqId.leftId);
                    const right = (0, checker_js_1.getIdentifierText)(idEqId.rightId);
                    return `(graph property) \`${left}\` = \`${right}\``;
                }
                case types_js_1.SyntaxKind.EdgeRhs:
                    return getEdgeHover(parent);
            }
            return types_js_1.SyntaxKind[parent.kind];
        }
        const fallback = types_js_1.SyntaxKind[n.kind];
        return fallback
            ? "(" + fallback.toLowerCase() + ")"
            : undefined;
    }
    switch (n.kind) {
        case types_js_1.SyntaxKind.GraphKeyword:
        case types_js_1.SyntaxKind.DigraphKeyword:
        case types_js_1.SyntaxKind.StrictKeyword:
            return getGraphHover(n.parent);
        case types_js_1.SyntaxKind.DirectedGraph:
        case types_js_1.SyntaxKind.UndirectedGraph:
            return getGraphHover(n);
        case types_js_1.SyntaxKind.DirectedEdgeOp:
        case types_js_1.SyntaxKind.UndirectedEdgeOp:
            return getEdgeHover(n.parent);
        default:
            return undefined;
    }
}
function getGraphHover(g) {
    const direction = g.kind === types_js_1.SyntaxKind.DirectedGraph ? "directed" : "undirected";
    const graphId = g.id;
    const strict = g.strict ? "strict " : "";
    return !!graphId
        ? `(${strict}${direction} graph) ${((0, checker_js_1.getIdentifierText)(graphId))}`
        : `(${strict}${direction} graph)`;
}
function getEdgeHover(n) {
    const p = n.parent;
    if (!p || p.rhs.length === 0)
        return undefined;
    let source = undefined;
    for (const curr of p.rhs) {
        if (curr === n)
            break;
        source = curr.target;
    }
    if (source === undefined)
        source = p.source;
    const edgeOpStr = (0, common_js_1.getEdgeStr)(n.operation.kind);
    return source === undefined
        ? undefined
        : `(edge) ${getEdgeSourceOrTargetText(source)} ${edgeOpStr} ${getEdgeSourceOrTargetText(n.target)}`;
}
function getEdgeSourceOrTargetText(n) {
    return n.kind === types_js_1.SyntaxKind.NodeId
        ? (0, checker_js_1.getIdentifierText)(n.id)
        : n.id !== undefined
            ? `${(0, checker_js_1.getIdentifierText)(n.id)}`
            : "sub graph";
}
//# sourceMappingURL=hover.js.map