"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.isFieldValue = exports.mapColumnExpressionToColumnId = exports.mapExpressionToFieldValue = exports.mapFieldValueToExpression = exports.getUnsuportedExpressionFromQlPredicate = exports.getFunctionsForColumnType = exports.getOperatorMatchingInputs = exports.reorder = void 0;
const adaptableQlUtils_1 = require("../../../Utilities/adaptableQlUtils");
const predicate_1 = require("../../../parser/src/predicate");
const booleanExpressionFunctions_1 = require("../../../Utilities/ExpressionFunctions/booleanExpressionFunctions");
const ObjectExtensions_1 = require("../../../Utilities/Extensions/ObjectExtensions");
const booleanExpressions_1 = require("./booleanExpressions");
const reorder = (predicate, from, to) => {
    const predicateCopy = (0, ObjectExtensions_1.deepClone)(predicate);
    // we start from the root so no need to traverse first level
    const [_, ...fromPath] = from.split('/');
    const [__, ...toPath] = to.split('/');
    // remove from old position and get the item
    // path = '0/1/2'
    let itemToMove = predicateCopy;
    let prev = null;
    for (const index of fromPath) {
        prev = itemToMove;
        itemToMove = itemToMove.args[parseInt(index)];
    }
    prev.args.splice(parseInt(fromPath[fromPath.length - 1]), 1);
    // find the parent into wich we want to insert the item
    let cursor = predicateCopy;
    let parent = null;
    for (const index of toPath) {
        parent = cursor;
        cursor = cursor.args[parseInt(index)];
    }
    parent.args.splice(parseInt(toPath[toPath.length - 1]), 0, itemToMove);
    return predicateCopy;
};
exports.reorder = reorder;
const getOperatorMatchingInputs = (columnType, inputs, includeAllInputs = false) => {
    if (Array.isArray(inputs[0])) {
        const matchingInput = inputs.find((input) => input[0] === columnType);
        const [_, ...restOfArgs] = matchingInput ?? [];
        return restOfArgs;
    }
    const [_, ...restOfArgs] = inputs;
    return includeAllInputs
        ? inputs
        : restOfArgs;
};
exports.getOperatorMatchingInputs = getOperatorMatchingInputs;
const getFunctionsForColumnType = (dataType, availableBooleanFunctions) => {
    const columnType = (0, adaptableQlUtils_1.mapColumnDataTypeToExpressionFunctionType)(dataType);
    return booleanExpressions_1.booleanExpressionsAvailableInQueryBuilder.filter((boolFnName) => {
        if (!availableBooleanFunctions.includes(boolFnName)) {
            return false;
        }
        const functionDef = booleanExpressionFunctions_1.booleanExpressionFunctions[boolFnName];
        const inputs = functionDef.inputs;
        let matchingInputTypes = [];
        if (inputs && Array.isArray(inputs[0])) {
            matchingInputTypes = inputs.find((input) => input[0] === columnType);
        }
        else {
            matchingInputTypes = inputs;
        }
        return matchingInputTypes?.[0] === columnType;
    });
};
exports.getFunctionsForColumnType = getFunctionsForColumnType;
const getUnsuportedExpressionFromQlPredicate = (predicate, context) => {
    if (!predicate) {
        return null;
    }
    if (typeof predicate === 'string' && (0, exports.isFieldValue)(predicate)) {
        const field = (0, exports.mapExpressionToFieldValue)(predicate);
        if (!context.supportedFields?.some((field) => field?.value === (0, exports.mapExpressionToFieldValue)(predicate))) {
            return `Expression uses an unregistered field: "${field}"`;
        }
        else {
            return null;
        }
    }
    if (typeof predicate === 'object' && 'errorMessage' in predicate) {
        return null;
    }
    if (typeof predicate !== 'object' || !('operator' in predicate) || !predicate.operator) {
        return null;
    }
    if (!(0, predicate_1.isQlLogicalOperator)(predicate.operator) &&
        !booleanExpressions_1.booleanExpressionsAvailableInQueryBuilder.includes(predicate.operator)) {
        return `${predicate.operator} is not supported in the Query Builder`;
    }
    if (predicate.args.length === 0) {
        return null;
    }
    let firstInvalidArg = null;
    for (let arg of predicate.args) {
        firstInvalidArg = (0, exports.getUnsuportedExpressionFromQlPredicate)(arg, context);
        if (firstInvalidArg) {
            break;
        }
    }
    if (firstInvalidArg) {
        return firstInvalidArg;
    }
    return null;
};
exports.getUnsuportedExpressionFromQlPredicate = getUnsuportedExpressionFromQlPredicate;
const mapFieldValueToExpression = (field) => `FIELD('${field}')`;
exports.mapFieldValueToExpression = mapFieldValueToExpression;
const mapExpressionToFieldValue = (expression) => {
    if (!expression) {
        return '';
    }
    try {
        return expression.match(/FIELD\(['"](.+)['"]\)/)?.[1];
    }
    catch (e) {
        return '';
    }
};
exports.mapExpressionToFieldValue = mapExpressionToFieldValue;
const mapColumnExpressionToColumnId = (expression) => {
    if (!expression) {
        return null;
    }
    try {
        return expression.match(/\[(.+)\]/)?.[1];
    }
    catch (e) {
        return expression;
    }
};
exports.mapColumnExpressionToColumnId = mapColumnExpressionToColumnId;
const isFieldValue = (expression) => {
    return typeof expression === 'string' && expression.includes('FIELD');
};
exports.isFieldValue = isFieldValue;
