"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.FlinkSQLCompletionParser = void 0;
const vscode_languageserver_1 = require("vscode-languageserver");
const completion_visitor_1 = require("./visitors/completion.visitor");
class FlinkSQLCompletionParser {
    constructor(tree, cursor) {
        this.tree = tree;
        this.cursor = cursor;
    }
    getSuggestions(metadataProvider) {
        try {
            const completionVisitor = new completion_visitor_1.CompletionVisitor(this.cursor, args => metadataProvider.getColumns(args));
            this.tree.accept(completionVisitor);
            const completions = completionVisitor.getSuggestions();
            const completionItems = [];
            const addCatalogSuggestions = () => {
                const catalogCompletions = metadataProvider.getCatalogs().map(c => ({
                    kind: vscode_languageserver_1.CompletionItemKind.Class,
                    label: c.label,
                    insertTextFormat: vscode_languageserver_1.InsertTextFormat.Snippet,
                    sortText: `AAD${c.label}`,
                    detail: `metadata catalog`,
                    data: 'catalog'
                }));
                completionItems.push(...catalogCompletions);
            };
            const addDatabaseSuggestions = (args) => {
                const databaseCompletions = metadataProvider.getDatabases(args).map(d => ({
                    kind: vscode_languageserver_1.CompletionItemKind.Enum,
                    label: d.label,
                    insertTextFormat: vscode_languageserver_1.InsertTextFormat.Snippet,
                    sortText: `AAC${d.label}`,
                    detail: `metadata database`,
                    data: 'database'
                }));
                completionItems.push(...databaseCompletions);
            };
            switch (completions.type) {
                case 'column': {
                    const relations = completions.relations.map(rel => ({
                        kind: vscode_languageserver_1.CompletionItemKind.EnumMember,
                        label: rel.label,
                        insertTextFormat: vscode_languageserver_1.InsertTextFormat.Snippet,
                        sortText: `AAB${rel.label}`,
                        detail: `${rel.category} in context`,
                        data: 'table'
                    }));
                    const columns = completions.columns.map(col => ({
                        kind: vscode_languageserver_1.CompletionItemKind.Field,
                        label: col.name,
                        insertTextFormat: vscode_languageserver_1.InsertTextFormat.Snippet,
                        sortText: `AAA${col.name}`,
                        detail: `column${col.relation ? ` of '${col.relation.label}' relation` : ''}`,
                        data: 'column'
                    }));
                    completionItems.push(...columns, ...relations);
                    break;
                }
                case 'relation': {
                    const sqlRelations = completions.relations.map(rel => ({
                        kind: vscode_languageserver_1.CompletionItemKind.EnumMember,
                        label: rel.label,
                        insertTextFormat: vscode_languageserver_1.InsertTextFormat.Snippet,
                        sortText: `AAB${rel.label}`,
                        detail: `${rel.category} in context`,
                        data: 'table'
                    }));
                    completionItems.push(...sqlRelations);
                    let args = {
                        catalog: completionVisitor.catalogUsed,
                        database: completionVisitor.databaseUsed
                    };
                    if (completions.incompleteReference) {
                        if (completions.incompleteReference.length === 1) {
                            args.database = completions.incompleteReference[0];
                        }
                        else if (completions.incompleteReference.length === 2) {
                            args = {
                                catalog: completions.incompleteReference[0],
                                database: completions.incompleteReference[1]
                            };
                        }
                    }
                    const tableCompletions = metadataProvider.getTables(args).map(t => ({
                        kind: vscode_languageserver_1.CompletionItemKind.EnumMember,
                        label: t.label,
                        insertTextFormat: vscode_languageserver_1.InsertTextFormat.Snippet,
                        sortText: `AAB${t.label}`,
                        detail: `metadata table`,
                        data: 'table'
                    }));
                    completionItems.push(...tableCompletions);
                    if (completions.incompleteReference === undefined || completions.incompleteReference.length == 1) {
                        if (completionVisitor.databaseUsed === undefined) {
                            const args = {
                                catalog: completions.incompleteReference?.[0] ?? completionVisitor.catalogUsed
                            };
                            addDatabaseSuggestions(args);
                        }
                    }
                    if (completions.incompleteReference === undefined) {
                        if (completionVisitor.catalogUsed === undefined && completionVisitor.databaseUsed === undefined) {
                            addCatalogSuggestions();
                        }
                    }
                    break;
                }
                case 'database': {
                    const args = {
                        catalog: completions.incompleteReference ?? completionVisitor.catalogUsed
                    };
                    addDatabaseSuggestions(args);
                    if (completions.incompleteReference === undefined) {
                        addCatalogSuggestions();
                    }
                    break;
                }
                case 'catalog': {
                    addCatalogSuggestions();
                    break;
                }
            }
            const snippets = completions.snippets.map(s => ({
                kind: vscode_languageserver_1.CompletionItemKind.Struct,
                label: s.label,
                insertTextFormat: vscode_languageserver_1.InsertTextFormat.Snippet,
                insertText: s.template,
                sortText: `AAAAA`,
                documentation: `Insert a snippet of query primary body`,
                detail: `code snippet`
            }));
            completionItems.push(...snippets);
            return completionItems;
        }
        catch (e) {
            return [];
        }
    }
}
exports.FlinkSQLCompletionParser = FlinkSQLCompletionParser;
