import * as lst from "vscode-languageserver-types";
import { findNodeAtOffset, getIdentifierText, isEdgeStatement } from "../checker.js";
import { isIdentifierNode } from "../index.js";
import { SyntaxKind, } from "../types.js";
import * as languageFacts from "./languageFacts.js";
import { escapeIdentifierText } from "./util.js";
export function getCompletions(doc, sourceFile, position) {
    const symbols = sourceFile.symbols;
    if (!symbols)
        throw "sourceFile is not bound";
    const g = sourceFile.graph;
    if (!g)
        return [];
    const offset = doc.offsetAt(position);
    const node = findNodeAtOffset(g, offset, true);
    if (!node)
        return [];
    const prevOffsetNode = findNodeAtOffset(g, offset - 1, true);
    const parent = node.parent;
    const prevOffsetNodeParent = prevOffsetNode?.parent;
    if ((parent?.parent && isEdgeStatement(parent.parent)) ||
        (prevOffsetNodeParent?.parent && isEdgeStatement(prevOffsetNodeParent.parent))) {
        return getNodeCompletions(symbols);
    }
    if (node.kind === SyntaxKind.AttributeContainer) {
        const openingBracket = node.openBracket;
        if (openingBracket.end - 1 > offset - 1) {
            const exclusions = prevOffsetNode?.kind === SyntaxKind.TextIdentifier && prevOffsetNode.symbol
                ? [prevOffsetNode.symbol.name]
                : undefined;
            return getNodeCompletions(symbols, exclusions);
        }
    }
    if (node.kind === SyntaxKind.TextIdentifier && parent?.kind === SyntaxKind.NodeId) {
        const exclusions = node.symbol ? [node.symbol.name] : undefined;
        return getNodeCompletions(symbols, exclusions);
    }
    if (node.kind === SyntaxKind.AttributeContainer ||
        (node.kind === SyntaxKind.CommaToken && parent?.kind === SyntaxKind.Assignment)) {
        return getAttributeCompletions(position);
    }
    const prevNode = findNodeAtOffset(g, node.pos - 1, true);
    if (!prevNode)
        return [];
    if (isIdentifierNode(prevNode)) {
        const p = prevNode.parent;
        if (p) {
            switch (p.kind) {
                case SyntaxKind.NodeId: {
                    return getNodeCompletions(symbols);
                }
                case SyntaxKind.Assignment: {
                    return getAssignmentCompletion(p);
                }
            }
        }
    }
    if (node.flags & 2 || node.end === node.pos) {
        const attribute = prevNode;
        if (!attribute)
            return [];
        if (!attribute.parent)
            throw "sourceFile is not bound";
        const parent = attribute.parent;
        if (parent.kind === SyntaxKind.Assignment) {
            return getAssignmentCompletion(parent);
        }
    }
    return [];
}
function getAssignmentCompletion(assignment) {
    const property = getIdentifierText(assignment.leftId);
    if (!property)
        return [];
    switch (property.toLowerCase()) {
        case "shape":
            return getShapeCompletions();
        case "color":
            return getColorCompletions();
        default:
            return [];
    }
}
function getShapeCompletions() {
    const kind = lst.CompletionItemKind.EnumMember;
    return languageFacts.shapes.map(s => ({
        kind,
        label: escapeIdentifierText(s),
    }));
}
function getColorCompletions() {
    const kind = lst.CompletionItemKind.Color;
    const colors = languageFacts.colors;
    return Object.keys(colors).map(label => ({
        kind,
        label,
        documentation: colors[label],
    }));
}
function getAttributeCompletions(posistion) {
    const kind = lst.CompletionItemKind.Property;
    const range = {
        start: posistion,
        end: posistion,
    };
    return languageFacts.attributes.map(label => ({
        kind,
        label,
        textEdit: {
            range,
            newText: `${escapeIdentifierText(label)}=`,
        },
    }));
}
function getNodeCompletions(symbols, exlucdedSymbols) {
    const res = new Array();
    for (const [key, value] of symbols) {
        if (exlucdedSymbols?.includes(key))
            continue;
        let kind = lst.CompletionItemKind.Variable;
        const a = value.firstMention.parent;
        if (a) {
            switch (a.kind) {
                case SyntaxKind.DirectedGraph:
                case SyntaxKind.UndirectedGraph:
                    kind = lst.CompletionItemKind.Class;
                    break;
            }
        }
        res.push({
            label: escapeIdentifierText(key),
            kind: kind,
        });
    }
    return res;
}
//# sourceMappingURL=completion.js.map