import * as _ from 'lodash-es';
import { EOF } from 'chevrotain';
import JDLAstBuilderVisitor from './jdl-ast-builder-visitor.js';
import { JDLLexer, tokens } from './lexer/lexer.js';
import JDLParser from './jdl-parser.js';
import performAdditionalSyntaxChecks from './validator.js';
import { checkTokens } from './self-checks/parsing-system-checker.js';
const parserSingleton = JDLParser.getParser();
parserSingleton.parse();
const rules = parserSingleton.getGAstProductions();
checkTokens(Object.values(tokens), Object.values(rules));
export function parse(input, startRule = 'prog') {
    const cst = getCst(input, startRule);
    const astBuilderVisitor = new JDLAstBuilderVisitor();
    return astBuilderVisitor.visit(cst);
}
export function getCst(input, startRule = 'prog') {
    const lexResult = JDLLexer.tokenize(input);
    if (lexResult.errors.length > 0) {
        throw Error(lexResult.errors[0].message);
    }
    parserSingleton.input = lexResult.tokens;
    const cst = parserSingleton[startRule]();
    if (parserSingleton.errors.length > 0) {
        throwParserError(parserSingleton.errors);
    }
    const extraSyntaxErrors = performAdditionalSyntaxChecks(cst);
    if (extraSyntaxErrors.length > 0) {
        throwSyntaxError(extraSyntaxErrors);
    }
    return cst;
}
function throwParserError(errors) {
    const parserError = errors[0];
    if (parserError.name === 'MismatchedTokenException') {
        throwErrorAboutInvalidToken(parserError);
    }
    const errorMessage = `${parserError.name}: ${parserError.message}`;
    const { token } = parserError;
    const errorMessageLocation = token.tokenType !== EOF ? `\n\tat line: ${token.startLine}, column: ${token.startColumn}` : '';
    throw Error(`${errorMessage}${errorMessageLocation}`);
}
function throwErrorAboutInvalidToken(parserError) {
    const { token } = parserError;
    const errorMessageBeginning = `Found an invalid token '${token.image}'`;
    const errorMessageLocation = token.tokenType !== EOF ? `, at line: ${token.startLine} and column: ${token.startColumn}` : '';
    const errorMessageComplement = 'Please make sure your JDL content does not use invalid characters, keywords or options.';
    throw Error(`${parserError.name}: ${errorMessageBeginning}${errorMessageLocation}.\n\t${errorMessageComplement}`);
}
function throwSyntaxError(errors) {
    throw Error(errors.map(error => `${error.message}\n\tat line: ${error.token.startLine}, column: ${error.token.startColumn}`).join('\n'));
}
export function getSyntacticAutoCompleteSuggestions(input, startRule = 'prog') {
    const lexResult = JDLLexer.tokenize(input);
    parserSingleton.input = lexResult.tokens;
    const syntacticSuggestions = parserSingleton.computeContentAssist(startRule, lexResult.tokens);
    return _.uniq(syntacticSuggestions.map(suggestion => suggestion.nextTokenType));
}
