import * as React from 'react';
import { Box, Flex } from 'rebass';
import { CheckBox } from '../../../../components/CheckBox';
import FormLayout, { FormRow } from '../../../../components/FormLayout';
import Panel from '../../../../components/Panel';
import { Select } from '../../../../components/Select';
import SimpleButton from '../../../../components/SimpleButton';
import { Tabs } from '../../../../components/Tabs';
import { Tag } from '../../../../components/Tag';
import { summarySupportedExpressions, WEIGHTED_AVERAGE_AGGREGATED_FUNCTION, } from '../../../../AdaptableState/Common/RowSummary';
import { mapColumnDataTypeToExpressionFunctionType } from '../../../../Utilities/adaptableQlUtils';
import { LayoutModuleId } from '../../../../Utilities/Constants/ModuleConstants';
import { aggregatedExpressionFunctions } from '../../../../Utilities/ExpressionFunctions/aggregatedScalarExpressionFunctions';
import { useAdaptable } from '../../../AdaptableContext';
import { SuspendToggleButton } from '../../../Components/Buttons/SuspendToggleButton';
import { ValueSelector } from '../../../Components/ValueSelector';
import { useOnePageAdaptableWizardContext } from '../../../Wizard/OnePageAdaptableWizard';
import { columnFilter } from './Utilities';
import ArrayExtensions from '../../../../Utilities/Extensions/ArrayExtensions';
export const areSummaryRowsValid = (layout) => {
    if (!layout.RowSummaries)
        return true;
    let valid = true;
    layout.RowSummaries?.find((rowSummary) => {
        for (const [_, fn] of Object.entries(rowSummary.ColumnsMap ?? {})) {
            if (!fn) {
                valid = 'All row summary columns must have an aggregation function.';
                return true;
            }
        }
    });
    return valid;
};
const availableExpressionsForColumnTypeCache = new Map();
const getAvailableExpressionsForColumnType = (columnType, availableScalarExpressions) => {
    const key = columnType;
    if (availableExpressionsForColumnTypeCache.has(key)) {
        return availableExpressionsForColumnTypeCache.get(key);
    }
    const columnInputType = mapColumnDataTypeToExpressionFunctionType(columnType);
    const expressions = Object.keys(availableScalarExpressions)
        .filter((availableExpression) => {
        if (!aggregatedExpressionFunctions.includes(availableExpression)) {
            // is custom
            return true;
        }
        return Boolean(summarySupportedExpressions.includes(availableExpression));
    })
        .map((expression) => {
        const expressionDef = availableScalarExpressions[expression];
        let firstArg = null;
        // filter out expressions without inputs defined
        if (!expressionDef?.inputs) {
            return null;
        }
        if (Array.isArray(expressionDef?.inputs?.[0])) {
            // @ts-ignore
            firstArg = expressionDef.inputs.find((input) => input.includes(columnInputType))?.[0];
        }
        else {
            firstArg = expressionDef.inputs[0];
        }
        if (columnInputType === firstArg) {
            return expression;
        }
        else {
            return null;
        }
    })
        .filter(Boolean);
    availableExpressionsForColumnTypeCache.set(key, expressions);
    return expressions;
};
export const RowSummarySectionSummary = () => {
    const adaptable = useAdaptable();
    const { data: layout } = useOnePageAdaptableWizardContext();
    return (React.createElement(Box, { display: 'flex', flexDirection: 'column' }, layout.RowSummaries?.length ? (layout.RowSummaries.map((rowSummary, index) => {
        return (React.createElement(React.Fragment, null,
            React.createElement(Box, { mr: 1, mb: 1, key: index },
                rowSummary.Position,
                ":",
                ' ',
                Object.keys(rowSummary.ColumnsMap).map((colId) => {
                    if (colId === 'Source' || colId === 'Uuid')
                        return null;
                    return (React.createElement(Tag, { mr: 1, key: colId },
                        rowSummary.ColumnsMap[colId],
                        "(",
                        adaptable.api.columnApi.getFriendlyNameForColumnId(colId),
                        ")"));
                }))));
    })) : (React.createElement(Tag, null, "No Row Summaries"))));
};
const RowSummaryEditor = React.memo(({ rowSummary, onChange, availableScalarExpressions, onDelete, }) => {
    const { data: layout } = useOnePageAdaptableWizardContext();
    const adaptable = useAdaptable();
    const columns = React.useMemo(() => {
        const colIds = adaptable.api.columnApi
            .getUIAvailableColumns()
            .filter((column) => {
            if (!['number', 'text', 'date'].includes(column.dataType))
                return false;
            return layout.TableColumns?.includes?.(column.columnId);
        })
            .map((c) => c.columnId);
        return ArrayExtensions.sortArrayWithOrder(colIds, Object.keys(rowSummary.ColumnsMap), {
            sortUnorderedItems: false,
        }).map((colId) => adaptable.api.columnApi.getColumnWithColumnId(colId));
    }, [rowSummary.ColumnsMap]);
    return (React.createElement(Panel, { header: React.createElement(Flex, { style: { width: '100%' } },
            React.createElement(Flex, { flex: 1, alignItems: "center" }, "Row Summary"),
            React.createElement(Box, { mr: 2 },
                React.createElement(SuspendToggleButton, { onSuspend: () => {
                        onChange({
                            ...rowSummary,
                            IsSuspended: true,
                        });
                    }, onUnSuspend: () => {
                        onChange({
                            ...rowSummary,
                            IsSuspended: false,
                        });
                    }, suspendableObject: rowSummary })),
            React.createElement(SimpleButton, { icon: "delete", onClick: () => {
                    onDelete();
                } })), p: 2 },
        React.createElement(FormLayout, null,
            React.createElement(FormRow, { label: "Position" },
                React.createElement(Select, { options: [
                        {
                            label: 'Top',
                            value: 'Top',
                        },
                        {
                            label: 'Bottom',
                            value: 'Bottom',
                        },
                    ], value: rowSummary.Position, onChange: (position) => {
                        onChange({
                            ...rowSummary,
                            Position: position,
                        });
                    } })),
            React.createElement(FormRow, { label: "" },
                React.createElement(CheckBox, { checked: rowSummary.IncludeOnlyFilteredRows ?? true, onChange: (IncludeOnlyFilteredRows) => {
                        onChange({
                            ...rowSummary,
                            IncludeOnlyFilteredRows,
                        });
                    } }, "Include Only Filtered Rows"))),
        React.createElement(Flex, { flexDirection: 'column', mt: 2, mb: 1 },
            React.createElement(Flex, { alignItems: "center", flex: 1, mb: 2 }, "Column Aggregations"),
            React.createElement(Panel, { bodyProps: { maxHeight: '100%' }, style: { height: 360 } },
                React.createElement(ValueSelector, { style: { maxHeight: '100%' }, showFilterInput: true, filter: columnFilter, toIdentifier: (column) => column.columnId, toLabel: (option) => option.friendlyName ?? option.columnId, options: columns, xSelectedLabel: () => {
                        return 'Active Aggregations:';
                    }, toListLabel: (column) => {
                        const label = column.friendlyName ?? column.columnId;
                        if (!(column.columnId in (rowSummary.ColumnsMap ?? {}))) {
                            return label;
                        }
                        const expressionOptions = getAvailableExpressionsForColumnType(column.dataType, availableScalarExpressions).map((expression) => ({
                            label: expression,
                            value: expression,
                        }));
                        // check out if this layout has a aggregation with weighted column
                        const aggregation = layout.TableAggregationColumns?.find((agg) => agg.ColumnId === column.columnId)?.AggFunc;
                        if (aggregation &&
                            typeof aggregation === 'object' &&
                            aggregation.weightedColumnId) {
                            expressionOptions.push({
                                label: 'WEIGHTERD_AVG',
                                value: WEIGHTED_AVERAGE_AGGREGATED_FUNCTION,
                            });
                        }
                        const expression = rowSummary.ColumnsMap[column.columnId];
                        return (React.createElement(Flex, null,
                            React.createElement(Flex, { mr: 2, alignItems: 'center' }, label),
                            React.createElement(Select, { value: expression, options: expressionOptions, onChange: (expression) => {
                                    onChange({
                                        ...rowSummary,
                                        ColumnsMap: {
                                            ...rowSummary.ColumnsMap,
                                            [column.columnId]: expression,
                                        },
                                    });
                                } })));
                    }, value: Object.keys(rowSummary.ColumnsMap), onChange: (colIds) => {
                        const newColumnsMap = {};
                        colIds.forEach((colId) => {
                            newColumnsMap[colId] = rowSummary.ColumnsMap[colId] ?? null;
                        });
                        onChange({
                            ...rowSummary,
                            ColumnsMap: newColumnsMap,
                        });
                    } })))));
});
export const RowSummarySection = (props) => {
    const adaptable = useAdaptable();
    const { data: layout } = useOnePageAdaptableWizardContext();
    const availableScalarExpressions = React.useMemo(() => {
        const sytemExpressions = adaptable.api.internalApi
            .getQueryLanguageService()
            .getModuleExpressionFunctionsMap(LayoutModuleId).aggregatedScalarFunctions;
        return sytemExpressions;
    }, []);
    return (React.createElement(Tabs, { style: { height: '100%' } },
        React.createElement(Tabs.Tab, null, "Row Summaries"),
        React.createElement(Tabs.Content, null,
            React.createElement("div", null,
                React.createElement(Flex, { mb: 1 },
                    React.createElement(Flex, { flex: 1 }),
                    React.createElement(SimpleButton, { onClick: () => {
                            props.onChange({
                                ...layout,
                                RowSummaries: [
                                    ...(layout.RowSummaries ?? []),
                                    {
                                        Position: 'Top',
                                        ColumnsMap: {},
                                        IncludeOnlyFilteredRows: true,
                                    },
                                ],
                            });
                        }, icon: "plus" }, "Add Row Summary")),
                (layout.RowSummaries ?? []).map((rowSummary, index) => {
                    return (React.createElement(RowSummaryEditor, { key: index, onDelete: () => {
                            const newSummaries = [...layout.RowSummaries];
                            newSummaries.splice(index, 1);
                            props.onChange({
                                ...layout,
                                RowSummaries: newSummaries,
                            });
                        }, availableScalarExpressions: availableScalarExpressions, rowSummary: rowSummary, onChange: (rowSummary) => {
                            const newSummaries = [...layout.RowSummaries];
                            newSummaries[index] = rowSummary;
                            props.onChange({
                                ...layout,
                                RowSummaries: newSummaries,
                            });
                        } }));
                })))));
};
