"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.QueryBuilder = exports.useQueryBuilderContext = void 0;
const tslib_1 = require("tslib");
const React = tslib_1.__importStar(require("react"));
const dnd_1 = require("../../dnd");
const rebass_1 = require("rebass");
const predicate_1 = require("../../../parser/src/predicate");
const mapQlPredicateToExpression_1 = require("../../../parser/src/predicate/mapQlPredicateToExpression");
const AdaptableContext_1 = require("../../../View/AdaptableContext");
const ErrorBox_1 = tslib_1.__importDefault(require("../../ErrorBox"));
const HelpBlock_1 = tslib_1.__importDefault(require("../../HelpBlock"));
const Panel_1 = tslib_1.__importDefault(require("../../Panel"));
const SimpleButton_1 = tslib_1.__importDefault(require("../../SimpleButton"));
const WarningBox_1 = require("../../WarningBox");
const QueryPredicateBuilder_1 = require("./QueryPredicateBuilder");
const utils_1 = require("./utils");
const QUERY_BUILDER_CLASSNAME = 'ab-QueryBuilder';
const QueryBuilderContext = React.createContext(null);
function useQueryBuilderContext() {
    const context = React.useContext(QueryBuilderContext);
    if (!context) {
        throw new Error('useQueryBuilderContext must be used within a QueryBuilderContext');
    }
    return context;
}
exports.useQueryBuilderContext = useQueryBuilderContext;
const QueryBuilder = (props) => {
    const adaptable = (0, AdaptableContext_1.useAdaptable)();
    const [qlPredicate, setQlPredicate] = React.useState(() => {
        const qlPredicate = (0, predicate_1.mapExpressionToQlPredicate)(props.query);
        return qlPredicate;
    });
    const [expressionStr, setExpressionStr] = React.useState(props.query);
    const handleQlPredicateChange = (qlPredicate) => {
        setQlPredicate(qlPredicate);
        if (qlPredicate && !('errorMessage' in qlPredicate)) {
            const newQuery = (0, mapQlPredicateToExpression_1.mapQlPredicateToExpression)(qlPredicate);
            props.onChange(newQuery);
            setExpressionStr(newQuery);
        }
    };
    const clearExpression = () => {
        const predicate = (0, predicate_1.mapExpressionToQlPredicate)('');
        setQlPredicate(predicate);
        setExpressionStr('');
        props.onChange('');
    };
    const booleanExpressions = React.useMemo(() => {
        const expressionMap = adaptable.api.internalApi
            .getQueryLanguageService()
            .getModuleExpressionFunctionsMap(props.module);
        const booleanExpressions = { ...expressionMap.booleanFunctions };
        const booleanExpressionsWithoutCombinators = booleanExpressions;
        delete booleanExpressionsWithoutCombinators.AND;
        delete booleanExpressionsWithoutCombinators.OR;
        return booleanExpressionsWithoutCombinators;
    }, []);
    const context = React.useMemo(() => {
        return {
            getColumns: props.getColumns,
            getFields: props.getFields,
            getExpressions: (columnType) => {
                return booleanExpressions
                    ? (0, utils_1.getFunctionsForColumnType)(columnType, Object.keys(booleanExpressions))
                    : [];
            },
            onQlPredicateChange: handleQlPredicateChange,
        };
    }, []);
    const clearExpressionButton = (React.createElement(SimpleButton_1.default, { onClick: () => {
            clearExpression();
        } }, "Clear Expression"));
    const unsupportedExpressionFunction = (0, utils_1.getUnsuportedExpressionFromQlPredicate)(qlPredicate, {
        supportedFields: props.getFields(),
    });
    let errorOrEditor = null;
    if (qlPredicate && 'errorMessage' in qlPredicate) {
        errorOrEditor = props.query?.includes?.('QUERY') ? (React.createElement(WarningBox_1.WarningBox, { "data-name": "unsupported-query-warning" },
            React.createElement(rebass_1.Flex, { alignItems: "center" },
                "Named Queries are not supported in the Query Builder",
                React.createElement(rebass_1.Box, { flex: 1 }),
                clearExpressionButton))) : (React.createElement(ErrorBox_1.default, null,
            React.createElement(rebass_1.Flex, null,
                qlPredicate.errorMessage,
                React.createElement(rebass_1.Box, { flex: 1 }),
                clearExpressionButton)));
    }
    else if (unsupportedExpressionFunction) {
        errorOrEditor = (React.createElement(WarningBox_1.WarningBox, { "data-name": "unsupported-expression-warning" }, unsupportedExpressionFunction));
    }
    else if (qlPredicate && !('errorMessage' in qlPredicate)) {
        errorOrEditor = (React.createElement(QueryPredicateBuilder_1.QueryPredicateBuilder, { isRoot: true, index: 0, id: "0", predicate: qlPredicate, onNewPredicate: (type) => {
                // add to its children
                const newPredicate = {
                    operator: type === 'filter' ? undefined : 'AND',
                    args: [],
                };
                handleQlPredicateChange({
                    ...qlPredicate,
                    args: [...qlPredicate.args, newPredicate],
                });
            }, onChange: (predicate) => {
                handleQlPredicateChange(predicate);
            } }));
    }
    return (React.createElement(dnd_1.DragDropContext, { onDragEnd: (result) => {
            if (!result.destination) {
                return;
            }
            const toPath = `${result.destination.droppableId}/${result.destination.index}`;
            const fromPath = result.draggableId;
            const predicate = (0, utils_1.reorder)(qlPredicate, fromPath, toPath);
            handleQlPredicateChange(predicate);
        } },
        React.createElement(QueryBuilderContext.Provider, { value: context },
            React.createElement(rebass_1.Box, { className: QUERY_BUILDER_CLASSNAME },
                React.createElement(HelpBlock_1.default, { "data-name": "query-builder-help", mt: 2, mb: 2, p: 2, fontSize: 3 }, "Build the Grid Filter by adding Column Conditions and AND / OR Groups as required"),
                errorOrEditor,
                React.createElement(Panel_1.default, { "data-name": "query-builder-expression-preview", variant: "default", header: "AdapTableQL Expression", mt: 3 },
                    React.createElement(rebass_1.Box, { className: `${QUERY_BUILDER_CLASSNAME}__expression`, minHeight: 48, my: 2, p: 3 }, expressionStr || 'Output Expression will display here'))))));
};
exports.QueryBuilder = QueryBuilder;
