import * as React from 'react';
import { Box, Flex, Text } from 'rebass';
import { CheckBox } from '../../../../components/CheckBox';
import DropdownButton from '../../../../components/DropdownButton';
import FormLayout, { FormRow } from '../../../../components/FormLayout';
import { Tabs } from '../../../../components/Tabs';
import { Tag } from '../../../../components/Tag';
import { useAdaptable } from '../../../AdaptableContext';
import { ValueSelector } from '../../../Components/ValueSelector';
import { useOnePageAdaptableWizardContext } from '../../../Wizard/OnePageAdaptableWizard';
import { columnFilter } from './Utilities';
import ArrayExtensions from '../../../../Utilities/Extensions/ArrayExtensions';
import { Select } from '../../../../components/Select';
import StringExtensions from '../../../../Utilities/Extensions/StringExtensions';
const WEIGHTED_AVERAGE_AGG_FN_NAME = 'weightedAvg';
export const isAggregationsSectionValid = (data) => {
    const weightedAvg = data.TableAggregationColumns
        ? (data.TableAggregationColumns || []).find(({ AggFunc }) => typeof AggFunc === 'object' &&
            AggFunc.type === 'weightedAverage')?.AggFunc
        : null;
    if (weightedAvg && !weightedAvg.weightedColumnId) {
        return 'The Weighted Average Aggregation requires a Weighted Column';
    }
    return true;
};
export const AggregationsSectionSummary = () => {
    const adaptable = useAdaptable();
    const { data: layout } = useOnePageAdaptableWizardContext();
    const entries = layout.TableAggregationColumns || [];
    let content = null;
    if (entries.length) {
        content = (React.createElement(FormLayout, null, entries.map(({ ColumnId, AggFunc }) => (React.createElement(FormRow, { key: ColumnId, label: adaptable.api.columnApi.getFriendlyNameForColumnId(ColumnId) },
            React.createElement(Tag, null, typeof AggFunc === 'object' ? AggFunc.type : AggFunc))))));
    }
    else {
        content = React.createElement(Tag, null, "No Aggregations");
    }
    return React.createElement(Box, null, content);
};
const ColumnRow = (props) => {
    const adaptable = useAdaptable();
    const aggValue = props.layout?.TableAggregationColumns?.find((agg) => agg.ColumnId === props.column.columnId)?.AggFunc;
    const adaptableAggFunctions = [];
    if (props.column.dataType === 'number') {
        adaptableAggFunctions.push(WEIGHTED_AVERAGE_AGG_FN_NAME);
    }
    const aggOptions = [...props.column.availableAggregationFunctions, ...adaptableAggFunctions].map((fnName) => {
        return {
            label: fnName,
            onClick: () => {
                let aggCols = props.layout.TableAggregationColumns || [];
                if (!aggCols) {
                    return;
                }
                const AggFuncValue = fnName === WEIGHTED_AVERAGE_AGG_FN_NAME
                    ? {
                        type: 'weightedAverage',
                        weightedColumnId: null,
                    }
                    : fnName;
                let found = false;
                aggCols = aggCols.map(({ ColumnId, AggFunc }) => {
                    if (ColumnId === props.column.columnId) {
                        found = true;
                        return {
                            ColumnId,
                            AggFunc: AggFuncValue,
                        };
                    }
                    return { ColumnId, AggFunc };
                });
                if (!found) {
                    aggCols.push({
                        ColumnId: props.column.columnId,
                        AggFunc: AggFuncValue,
                    });
                }
                props.onChangeAggFunction(aggCols);
            },
        };
    });
    const numericColumnsOptions = props.numberColumns
        .filter((col) => col.columnId !== props.column.columnId)
        .map((col) => {
        return {
            label: col.friendlyName,
            onClick: () => {
                let aggCols = [...(props.layout.TableAggregationColumns || [])];
                if (!aggCols || !aggCols.length) {
                    return;
                }
                const AggFuncValue = {
                    type: 'weightedAverage',
                    weightedColumnId: col.columnId,
                };
                let found = false;
                aggCols = aggCols.map(({ ColumnId, AggFunc }) => {
                    if (ColumnId === props.column.columnId) {
                        found = true;
                        return {
                            ColumnId,
                            AggFunc: AggFuncValue,
                        };
                    }
                    return { ColumnId, AggFunc };
                });
                if (!found) {
                    aggCols.push({
                        ColumnId: props.column.columnId,
                        AggFunc: AggFuncValue,
                    });
                }
                props.onChangeAggFunction(aggCols);
            },
        };
    });
    const currentAggFnName = props.aggregationColumnsMap[props.column.columnId];
    let weightName = null;
    if (typeof aggValue === 'object' && aggValue.type === 'weightedAverage') {
        weightName = aggValue.weightedColumnId
            ? adaptable.api.columnApi.getFriendlyNameForColumnId(aggValue.weightedColumnId)
            : 'Select Weight';
    }
    return (React.createElement(Flex, { alignItems: "center" },
        props.column.friendlyName,
        aggValue && (React.createElement(DropdownButton, { columns: ['label'], items: aggOptions, ml: 2 }, currentAggFnName)),
        currentAggFnName === WEIGHTED_AVERAGE_AGG_FN_NAME && (React.createElement(Flex, { backgroundColor: "primary", ml: 3, alignItems: "center" },
            React.createElement(Text, null, "Weight"),
            ' ',
            React.createElement(DropdownButton, { columns: ['label'], items: numericColumnsOptions, ml: 2 }, weightName)))));
};
export const AggregationsSection = (props) => {
    const adaptable = useAdaptable();
    const { data: layout } = useOnePageAdaptableWizardContext();
    const allAggregableColumns = adaptable.api.columnApi.getAggregatableColumns();
    const allColumns = adaptable.api.columnApi.getUIAvailableColumns();
    const numberColumns = adaptable.api.columnApi.getNumericColumns();
    const sortedAggregableColumns = React.useMemo(() => {
        return ArrayExtensions.sortArrayWithOrder(allAggregableColumns.map((col) => col.columnId), (layout.TableAggregationColumns ?? []).map((agg) => agg.ColumnId), { sortUnorderedItems: false }).map((colId) => adaptable.api.columnApi.getColumnWithColumnId(colId));
    }, [layout, allAggregableColumns]);
    const handleColumnsSelectionChange = React.useCallback((columnIds) => {
        const currentAggsMap = (layout.TableAggregationColumns || []).reduce((acc, { ColumnId, AggFunc }) => {
            acc[ColumnId] = AggFunc;
            return acc;
        }, {});
        props.onChange({
            ...layout,
            TableAggregationColumns: columnIds.map((colId) => {
                const AggFunc = currentAggsMap[colId] ?? adaptable.api.columnApi.getDefaultAggFunc(colId);
                return {
                    ColumnId: colId,
                    AggFunc,
                };
            }),
        });
    }, [layout]);
    const handleAggregationChange = React.useCallback((aggFunctions) => {
        props.onChange({
            ...layout,
            TableAggregationColumns: aggFunctions,
        });
    }, [layout]);
    const aggregationColumnsMap = React.useMemo(() => {
        const allColumnsMap = allColumns.reduce((acc, col) => {
            acc[col.columnId] = col;
            return acc;
        }, {});
        return (layout.TableAggregationColumns || []).reduce((acc, { ColumnId: colId, AggFunc }) => {
            let fn = AggFunc;
            let fnName = '';
            if (typeof fn === 'boolean') {
                fnName = allColumnsMap[colId].aggregationFunction;
            }
            if (typeof fn === 'object' && fn.type === 'weightedAverage') {
                fnName = WEIGHTED_AVERAGE_AGG_FN_NAME;
            }
            else if (typeof fn === 'string') {
                fnName = fn;
            }
            acc[colId] = fnName;
            return acc;
        }, {});
    }, [layout]);
    const handleSuppressAggFuncInHeader = (checked) => {
        props.onChange({
            ...layout,
            SuppressAggFuncInHeader: checked,
        });
    };
    return (React.createElement(Tabs, { style: { height: '100%' } },
        React.createElement(Tabs.Tab, null, "Column Aggregations"),
        React.createElement(Tabs.Content, null,
            React.createElement(Flex, null,
                React.createElement(FormLayout, null,
                    React.createElement(FormRow, { label: 'Omit Aggregation from Header' },
                        React.createElement(CheckBox, { checked: layout.SuppressAggFuncInHeader, onChange: handleSuppressAggFuncInHeader })),
                    React.createElement(FormRow, { label: 'Grand Total Row' },
                        React.createElement(Select, { style: { width: 120 }, options: ['top', 'bottom'].map((position) => {
                                return {
                                    label: StringExtensions.CapitaliseFirstLetter(position),
                                    value: position,
                                };
                            }), placeholder: "Off", value: layout.GrandTotalRow, onChange: (value) => {
                                props.onChange({
                                    ...layout,
                                    GrandTotalRow: value,
                                });
                            }, isClearable: true })))),
            React.createElement(ValueSelector, { showFilterInput: true, showSelectedOnlyPosition: "top", filter: columnFilter, toIdentifier: (option) => `${option.columnId}`, toLabel: (option) => option.friendlyName ?? option.columnId, toListLabel: (column) => (React.createElement(ColumnRow, { onChangeAggFunction: handleAggregationChange, layout: layout, column: column, aggregationColumnsMap: aggregationColumnsMap, numberColumns: numberColumns })), options: sortedAggregableColumns, value: (layout.TableAggregationColumns || []).map((agg) => agg.ColumnId), allowReorder: () => true, xSelectedLabel: () => {
                    return `Active aggregations:`;
                }, onChange: handleColumnsSelectionChange }))));
};
