import isEqual from 'lodash/isEqual';
import { isPivotLayoutModel } from '../../layout-manager/src/isPivotLayoutModel';
import { normalizeTableLayoutModel, normalizePivotLayoutModel, } from '../../layout-manager/src/normalizeLayoutModel';
import { simplifyTableLayoutModel, simplifyPivotLayoutModel, } from '../../layout-manager/src/simplifyLayoutModel';
import { isWeightedAverageAggregation, WEIGHTED_AVERAGE_AGG_FN_NAME, isWeightedAverageAggFuncName, } from '../../AdaptableState/Common/AggregationColumns';
import { removeAdaptableObjectPrimitivesInline } from '../../Utilities/Helpers/AdaptableHelper';
export const layoutStateToLayoutModel = (layout) => {
    if (isPivotLayout(layout)) {
        return pivotLayoutToPivotLayoutModel(layout);
    }
    return tableLayoutToTableLayoutModel(layout);
};
export const layoutModelToLayoutState = (layoutModel, defaults) => {
    if (isPivotLayoutModel(layoutModel)) {
        return pivotLayoutModelToPivotLayout(layoutModel, defaults);
    }
    return tableLayoutModelToTableLayout(layoutModel, defaults);
};
function cleanupAdaptableObjectPrimitives(layout) {
    if (layout.TableAggregationColumns) {
        layout.TableAggregationColumns.forEach((AggValue) => {
            removeAdaptableObjectPrimitivesInline(AggValue);
            if (typeof AggValue.AggFunc === 'object' && AggValue.AggFunc) {
                removeAdaptableObjectPrimitivesInline(AggValue.AggFunc);
            }
        });
    }
    if (layout.ColumnHeaders) {
        removeAdaptableObjectPrimitivesInline(layout.ColumnHeaders);
    }
    if (layout.ColumnVisibility) {
        removeAdaptableObjectPrimitivesInline(layout.ColumnVisibility);
    }
    if (layout.ColumnWidths) {
        removeAdaptableObjectPrimitivesInline(layout.ColumnWidths);
    }
    if (layout.RowGroupValues) {
        removeAdaptableObjectPrimitivesInline(layout.RowGroupValues);
    }
}
/**
 * Compares 2 Layouts for equality
 * @param layout1 First Layout
 * @param layout2 Second Layout
 */
export const areLayoutsEqual = (layout1, layout2) => {
    if (!layout1 && !layout2) {
        return true;
    }
    if (!layout1 || !layout2) {
        return false;
    }
    return isEqual(normalizeLayout(layout1), normalizeLayout(layout2));
};
export const normalizeLayout = (layout, options) => {
    if (isPivotLayout(layout)) {
        return normalizePivotLayout(layout);
    }
    return normalizeTableLayout(layout, options);
};
export const normalizeTableLayout = (tableLayout, options) => {
    const Source = tableLayout.Source;
    const Uuid = tableLayout.Uuid;
    const AdaptableVersion = tableLayout.AdaptableVersion;
    const ColumnFilters = tableLayout.ColumnFilters;
    const GridFilter = tableLayout.GridFilter;
    let model = tableLayoutToTableLayoutModel(tableLayout);
    model = normalizeTableLayoutModel(model, options);
    tableLayout = tableLayoutModelToTableLayout(model, tableLayout);
    if (Source) {
        tableLayout.Source = Source;
    }
    if (Uuid) {
        tableLayout.Uuid = Uuid;
    }
    if (AdaptableVersion) {
        tableLayout.AdaptableVersion = AdaptableVersion;
    }
    if (ColumnFilters) {
        tableLayout.ColumnFilters = ColumnFilters;
    }
    if (GridFilter) {
        tableLayout.GridFilter = GridFilter;
    }
    return tableLayout;
};
export const normalizePivotLayout = (pivotLayout) => {
    const Source = pivotLayout.Source;
    const Uuid = pivotLayout.Uuid;
    const AdaptableVersion = pivotLayout.AdaptableVersion;
    const ColumnFilters = pivotLayout.ColumnFilters;
    const GridFilter = pivotLayout.GridFilter;
    let model = pivotLayoutToPivotLayoutModel(pivotLayout);
    model = normalizePivotLayoutModel(model);
    pivotLayout = pivotLayoutModelToPivotLayout(model, pivotLayout);
    if (Source) {
        pivotLayout.Source = Source;
    }
    if (Uuid) {
        pivotLayout.Uuid = Uuid;
    }
    if (AdaptableVersion) {
        pivotLayout.AdaptableVersion = AdaptableVersion;
    }
    if (ColumnFilters) {
        pivotLayout.ColumnFilters = ColumnFilters;
    }
    if (GridFilter) {
        pivotLayout.GridFilter = GridFilter;
    }
    return pivotLayout;
};
const errorOnceMessages = new Map();
const errorOnce = (message) => {
    if (errorOnceMessages.get(message)) {
        return;
    }
    console.error(message);
    errorOnceMessages.set(message, true);
};
export const checkForDuplicateColumns = (layout) => {
    if (layout.TableColumns) {
        const set = new Set(layout.TableColumns);
        if (set.size !== layout.TableColumns.length) {
            layout.TableColumns.reduce((acc, col) => {
                acc[col] = (acc[col] || 0) + 1;
                if (acc[col] > 1) {
                    // if you change this message, make sure you also update the associated test error-on-duplicate-column.spec.ts
                    errorOnce(`Duplicate column "${col}" in layout "${layout.Name}"!`);
                }
                return acc;
            }, {});
        }
    }
};
export const tableLayoutToTableLayoutModel = (tableLayout) => {
    tableLayout = structuredClone(tableLayout);
    cleanupAdaptableObjectPrimitives(tableLayout);
    if (tableLayout.RowGroupValues) {
        // @ts-ignore
        delete tableLayout.RowGroupValues.Source;
        // @ts-ignore
        delete tableLayout.RowGroupValues.Uuid;
        // @ts-ignore
        delete tableLayout.RowGroupValues.AdaptableVersion;
    }
    delete tableLayout.ColumnHeaders;
    const TableAggregationColumns = (tableLayout.TableAggregationColumns || []).map(({ ColumnId, AggFunc }) => {
        return {
            ColumnId,
            AggFunc: toAggFunc(AggFunc),
        };
    });
    const result = simplifyTableLayoutModel({
        SuppressAggFuncInHeader: tableLayout.SuppressAggFuncInHeader,
        TableColumns: tableLayout.TableColumns,
        ColumnWidths: tableLayout.ColumnWidths,
        ColumnVisibility: tableLayout.ColumnVisibility,
        ColumnSorts: tableLayout.ColumnSorts,
        // ColumnHeaders: tableLayout.ColumnHeaders,
        RowGroupedColumns: tableLayout.RowGroupedColumns,
        ColumnPinning: tableLayout.ColumnPinning,
        RowGroupValues: tableLayout.RowGroupValues
            ? tableLayout.RowGroupValues.RowGroupDefaultBehavior === 'always-collapsed' ||
                tableLayout.RowGroupValues.RowGroupDefaultBehavior === 'always-expanded'
                ? {
                    RowGroupDisplay: tableLayout.RowGroupValues.RowGroupDefaultBehavior,
                }
                : {
                    RowGroupDisplay: tableLayout.RowGroupValues.RowGroupDefaultBehavior,
                    Values: tableLayout.RowGroupValues.ExceptionGroupKeys || [],
                }
            : undefined,
        TableAggregationColumns: TableAggregationColumns,
        GrandTotalRow: tableLayout.GrandTotalRow,
    });
    if (tableLayout.RowGroupDisplayType) {
        result.RowGroupDisplayType = tableLayout.RowGroupDisplayType;
    }
    if (tableLayout.ColumnFilters) {
        result.ColumnFilters = tableLayout.ColumnFilters;
    }
    if (tableLayout.GridFilter) {
        result.GridFilter = tableLayout.GridFilter;
    }
    return result;
};
export const pivotLayoutToPivotLayoutModel = (pivotLayout) => {
    pivotLayout = structuredClone(pivotLayout);
    cleanupAdaptableObjectPrimitives(pivotLayout);
    delete pivotLayout.ColumnHeaders;
    const result = simplifyPivotLayoutModel({
        SuppressAggFuncInHeader: pivotLayout.SuppressAggFuncInHeader,
        ColumnWidths: pivotLayout.ColumnWidths,
        ColumnVisibility: pivotLayout.ColumnVisibility,
        ColumnSorts: pivotLayout.ColumnSorts,
        PivotGroupedColumns: pivotLayout.PivotGroupedColumns,
        ColumnPinning: pivotLayout.ColumnPinning,
        PivotColumns: pivotLayout.PivotColumns,
        PivotExpandLevel: pivotLayout.PivotExpandLevel,
        PivotAggregationColumns: (pivotLayout.PivotAggregationColumns || []).map(({ ColumnId, AggFunc, TotalColumn }) => {
            return {
                ColumnId,
                AggFunc: toAggFunc(AggFunc),
                TotalColumn,
            };
        }),
        GrandTotalRow: pivotLayout.GrandTotalRow,
        GrandTotalColumn: pivotLayout.GrandTotalColumn,
        PivotGroupTotalColumn: pivotLayout.PivotGroupTotalColumn,
        RowGroupValues: pivotLayout.RowGroupValues
            ? pivotLayout.RowGroupValues.RowGroupDefaultBehavior === 'always-collapsed' ||
                pivotLayout.RowGroupValues.RowGroupDefaultBehavior === 'always-expanded'
                ? {
                    RowGroupDisplay: pivotLayout.RowGroupValues.RowGroupDefaultBehavior,
                }
                : {
                    RowGroupDisplay: pivotLayout.RowGroupValues.RowGroupDefaultBehavior,
                    Values: pivotLayout.RowGroupValues.ExceptionGroupKeys || [],
                }
            : undefined,
    });
    if (pivotLayout.ColumnFilters) {
        result.ColumnFilters = pivotLayout.ColumnFilters;
    }
    if (pivotLayout.GridFilter) {
        result.GridFilter = pivotLayout.GridFilter;
    }
    return result;
};
function toAggFunc(aggFunc) {
    if (isWeightedAverageAggregation(aggFunc)) {
        return { aggFunc: WEIGHTED_AVERAGE_AGG_FN_NAME, weightedColumnId: aggFunc.weightedColumnId };
    }
    return { aggFunc };
}
export const tableLayoutModelToTableLayout = (layoutModel, defaults) => {
    const tableLayout = {
        ...defaults,
        TableColumns: layoutModel.TableColumns,
        ColumnWidths: layoutModel.ColumnWidths,
        ColumnVisibility: layoutModel.ColumnVisibility,
        ColumnSorts: layoutModel.ColumnSorts,
    };
    if (layoutModel.RowGroupDisplayType) {
        tableLayout.RowGroupDisplayType = layoutModel.RowGroupDisplayType;
    }
    if (layoutModel.RowGroupedColumns) {
        tableLayout.RowGroupedColumns = layoutModel.RowGroupedColumns;
    }
    else {
        delete tableLayout.RowGroupedColumns;
    }
    if (layoutModel.ColumnPinning) {
        tableLayout.ColumnPinning = layoutModel.ColumnPinning;
    }
    else {
        delete tableLayout.ColumnPinning;
    }
    if (layoutModel.RowGroupValues) {
        tableLayout.RowGroupValues = {
            RowGroupDefaultBehavior: layoutModel.RowGroupValues.RowGroupDisplay,
        };
        if ((layoutModel.RowGroupValues.RowGroupDisplay === 'collapsed' ||
            layoutModel.RowGroupValues.RowGroupDisplay === 'expanded') &&
            layoutModel.RowGroupValues.Values) {
            // @ts-ignore
            tableLayout.RowGroupValues.ExceptionGroupKeys = layoutModel.RowGroupValues.Values;
        }
    }
    else {
        delete tableLayout.RowGroupValues;
    }
    if (layoutModel.TableAggregationColumns) {
        tableLayout.TableAggregationColumns = layoutModel.TableAggregationColumns.map(({ ColumnId, AggFunc }) => {
            return {
                ColumnId,
                AggFunc: toAggregationColumnValue(AggFunc),
            };
        });
    }
    else {
        delete tableLayout.TableAggregationColumns;
    }
    if (layoutModel.GrandTotalRow) {
        tableLayout.GrandTotalRow = layoutModel.GrandTotalRow;
    }
    else {
        delete tableLayout.GrandTotalRow;
    }
    if (layoutModel.ColumnFilters) {
        tableLayout.ColumnFilters = layoutModel.ColumnFilters;
    }
    if (layoutModel.GridFilter) {
        tableLayout.GridFilter = layoutModel.GridFilter;
    }
    cleanupAdaptableObjectPrimitives(tableLayout);
    return tableLayout;
};
function toAggregationColumnValue(columnAggregationModel) {
    return columnAggregationModel &&
        typeof columnAggregationModel.aggFunc === 'string' &&
        isWeightedAverageAggFuncName(columnAggregationModel.aggFunc)
        ? {
            type: 'weightedAverage',
            weightedColumnId: columnAggregationModel.weightedColumnId,
        }
        : columnAggregationModel.aggFunc;
}
export const pivotLayoutModelToPivotLayout = (layoutModel, defaults) => {
    const pivotLayout = {
        ...defaults,
        PivotColumns: layoutModel.PivotColumns,
        TableColumns: layoutModel.TableColumns,
        ColumnWidths: layoutModel.ColumnWidths,
        ColumnVisibility: layoutModel.ColumnVisibility,
        ColumnSorts: layoutModel.ColumnSorts,
        ColumnPinning: layoutModel.ColumnPinning,
        PivotExpandLevel: layoutModel.PivotExpandLevel,
    };
    if (layoutModel.PivotGroupedColumns) {
        pivotLayout.PivotGroupedColumns = layoutModel.PivotGroupedColumns;
    }
    else {
        delete pivotLayout.PivotGroupedColumns;
    }
    if (layoutModel.RowGroupValues) {
        pivotLayout.RowGroupValues = {
            RowGroupDefaultBehavior: layoutModel.RowGroupValues.RowGroupDisplay,
        };
        if ((layoutModel.RowGroupValues.RowGroupDisplay === 'collapsed' ||
            layoutModel.RowGroupValues.RowGroupDisplay === 'expanded') &&
            layoutModel.RowGroupValues.Values) {
            // @ts-ignore
            pivotLayout.RowGroupValues.ExceptionGroupKeys = layoutModel.RowGroupValues.Values;
        }
    }
    else {
        delete pivotLayout.RowGroupValues;
    }
    if (layoutModel.GrandTotalRow) {
        pivotLayout.GrandTotalRow = layoutModel.GrandTotalRow;
    }
    else {
        delete pivotLayout.GrandTotalRow;
    }
    if (layoutModel.GrandTotalColumn) {
        pivotLayout.GrandTotalColumn = layoutModel.GrandTotalColumn;
    }
    else {
        delete pivotLayout.GrandTotalColumn;
    }
    if (layoutModel.PivotGroupTotalColumn) {
        pivotLayout.PivotGroupTotalColumn = layoutModel.PivotGroupTotalColumn;
    }
    else {
        delete pivotLayout.PivotGroupTotalColumn;
    }
    if (layoutModel.PivotAggregationColumns) {
        pivotLayout.PivotAggregationColumns = (layoutModel.PivotAggregationColumns || []).map(({ ColumnId, AggFunc, TotalColumn }) => ({
            ColumnId,
            AggFunc: toAggregationColumnValue(AggFunc),
            TotalColumn,
        }));
    }
    else {
        delete pivotLayout.PivotAggregationColumns;
    }
    if (layoutModel.ColumnFilters) {
        pivotLayout.ColumnFilters = layoutModel.ColumnFilters;
    }
    if (layoutModel.GridFilter) {
        pivotLayout.GridFilter = layoutModel.GridFilter;
    }
    return pivotLayout;
};
export const isPivotLayout = (layout) => Array.isArray(layout.PivotColumns);
