"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.getCompletions = getCompletions;
const lst = __importStar(require("vscode-languageserver-types"));
const checker_js_1 = require("../checker.js");
const index_js_1 = require("../index.js");
const types_js_1 = require("../types.js");
const languageFacts = __importStar(require("./languageFacts.js"));
const util_js_1 = require("./util.js");
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 = (0, checker_js_1.findNodeAtOffset)(g, offset, true);
    if (!node)
        return [];
    const prevOffsetNode = (0, checker_js_1.findNodeAtOffset)(g, offset - 1, true);
    const parent = node.parent;
    const prevOffsetNodeParent = prevOffsetNode === null || prevOffsetNode === void 0 ? void 0 : prevOffsetNode.parent;
    if (((parent === null || parent === void 0 ? void 0 : parent.parent) && (0, checker_js_1.isEdgeStatement)(parent.parent)) ||
        ((prevOffsetNodeParent === null || prevOffsetNodeParent === void 0 ? void 0 : prevOffsetNodeParent.parent) && (0, checker_js_1.isEdgeStatement)(prevOffsetNodeParent.parent))) {
        return getNodeCompletions(symbols);
    }
    if (node.kind === types_js_1.SyntaxKind.AttributeContainer) {
        const openingBracket = node.openBracket;
        if (openingBracket.end - 1 > offset - 1) {
            const exclusions = (prevOffsetNode === null || prevOffsetNode === void 0 ? void 0 : prevOffsetNode.kind) === types_js_1.SyntaxKind.TextIdentifier && prevOffsetNode.symbol
                ? [prevOffsetNode.symbol.name]
                : undefined;
            return getNodeCompletions(symbols, exclusions);
        }
    }
    if (node.kind === types_js_1.SyntaxKind.TextIdentifier && (parent === null || parent === void 0 ? void 0 : parent.kind) === types_js_1.SyntaxKind.NodeId) {
        const exclusions = node.symbol ? [node.symbol.name] : undefined;
        return getNodeCompletions(symbols, exclusions);
    }
    if (node.kind === types_js_1.SyntaxKind.AttributeContainer ||
        (node.kind === types_js_1.SyntaxKind.CommaToken && (parent === null || parent === void 0 ? void 0 : parent.kind) === types_js_1.SyntaxKind.Assignment)) {
        return getAttributeCompletions(position);
    }
    const prevNode = (0, checker_js_1.findNodeAtOffset)(g, node.pos - 1, true);
    if (!prevNode)
        return [];
    if ((0, index_js_1.isIdentifierNode)(prevNode)) {
        const p = prevNode.parent;
        if (p) {
            switch (p.kind) {
                case types_js_1.SyntaxKind.NodeId: {
                    return getNodeCompletions(symbols);
                }
                case types_js_1.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 === types_js_1.SyntaxKind.Assignment) {
            return getAssignmentCompletion(parent);
        }
    }
    return [];
}
function getAssignmentCompletion(assignment) {
    const property = (0, checker_js_1.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: (0, util_js_1.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: `${(0, util_js_1.escapeIdentifierText)(label)}=`,
        },
    }));
}
function getNodeCompletions(symbols, exlucdedSymbols) {
    const res = new Array();
    for (const [key, value] of symbols) {
        if (exlucdedSymbols === null || exlucdedSymbols === void 0 ? void 0 : exlucdedSymbols.includes(key))
            continue;
        let kind = lst.CompletionItemKind.Variable;
        const a = value.firstMention.parent;
        if (a) {
            switch (a.kind) {
                case types_js_1.SyntaxKind.DirectedGraph:
                case types_js_1.SyntaxKind.UndirectedGraph:
                    kind = lst.CompletionItemKind.Class;
                    break;
            }
        }
        res.push({
            label: (0, util_js_1.escapeIdentifierText)(key),
            kind: kind,
        });
    }
    return res;
}
//# sourceMappingURL=completion.js.map