"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.mapExpressionToQlPredicate = exports.isArgumentColumnOrField = void 0;
const booleanExpressionFunctions_1 = require("../../../Utilities/ExpressionFunctions/booleanExpressionFunctions");
const index_1 = require("../index");
const types_1 = require("../types");
const types_2 = require("./types");
const isArgumentColumnOrField = (arg) => {
    return arg && typeof arg === 'string' && (arg.includes('[') || arg.includes('FIELD'));
};
exports.isArgumentColumnOrField = isArgumentColumnOrField;
function mapAstToQlPredicate(ast) {
    const operator = getOperatorFromAST(ast);
    if (!(0, types_1.isAST_Function)(ast)) {
        return;
    }
    if (!operator || !(0, booleanExpressionFunctions_1.isBooleanAdaptableQlFunction)(operator)) {
        throw {
            errorMessage: `Only boolean functions are supported!`,
        };
    }
    const mapArgToPlArgs = (arg) => {
        if (typeof arg === 'object' && !Array.isArray(arg) && 'type' in arg) {
            if (arg.type === 'COL') {
                return [`[${arg.args[0]}]`];
            }
            // special case for FIELD
            if (arg.type === 'FIELD') {
                // we are keeping the expression to know we are dealing with a field
                return `FIELD('${arg.args[0]}')`;
            }
            if (arg.type === 'DATE') {
                return `DATE("${arg.args[0]}")`;
            }
            return mapAstToQlPredicate(arg);
        }
        if (['string', 'boolean', 'number'].includes(typeof arg)) {
            return arg;
        }
        if (arg && Array.isArray(arg)) {
            return arg.map((a) => mapArgToPlArgs(a)).flat();
        }
        return null;
    };
    const args = ast.args
        .map(mapArgToPlArgs)
        .filter((arg) => arg !== null && arg !== undefined)
        .flat();
    if (!(0, types_2.isQlLogicalOperator)(operator)) {
        // this throws
        if (!(0, exports.isArgumentColumnOrField)(args[0])) {
            throw {
                errorMessage: 'First Argument must be an Adaptable Column or Field!',
            };
        }
    }
    return {
        operator,
        args,
    };
}
function mapExpressionToQlPredicate(expression) {
    try {
        if (!expression) {
            // return a sensible default
            return {
                operator: 'AND',
                args: [],
            };
        }
        const ast = (0, index_1.getAST)(expression);
        const astRootNode = ast === null || ast === void 0 ? void 0 : ast[0];
        // TEST IS ROOT
        if (!astRootNode || !(0, types_1.isAST_Function)(astRootNode)) {
            throw { errorMessage: `Invalid expression: ${expression}` };
        }
        const operator = getOperatorFromAST(astRootNode);
        if (!operator || !(0, booleanExpressionFunctions_1.isBooleanAdaptableQlFunction)(operator)) {
            return { errorMessage: `Only boolean functions are supported!` };
        }
        const inputs = astRootNode.args;
        const qlPredicate = mapAstToQlPredicate(astRootNode);
        if (!(0, types_2.isQlLogicalOperator)(qlPredicate.operator)) {
            return {
                operator: 'AND',
                args: [qlPredicate],
            };
        }
        else {
            return qlPredicate;
        }
    }
    catch (err) {
        return {
            errorMessage: `Query Builder does not support the expression: ${expression}`,
        };
    }
}
exports.mapExpressionToQlPredicate = mapExpressionToQlPredicate;
function getOperatorFromAST(astRootNode) {
    if (!['INFIX', 'FUNCTION', 'VALUE_REF'].includes(astRootNode.metaInfo)) {
        return undefined;
    }
    return astRootNode.type;
}
