import { ColumnFilterModuleId, GridFilterModuleId, } from '../../Utilities/Constants/ModuleConstants';
import ArrayExtensions from '../../Utilities/Extensions/ArrayExtensions';
import { ApiBase } from '../Implementation/ApiBase';
import { areLayoutsEqual, isPivotLayout } from '../Implementation/LayoutHelpers';
import ObjectFactory from '../../Utilities/ObjectFactory';
import Helper from '../../Utilities/Helpers/Helper';
import AdaptableHelper from '../../Utilities/Helpers/AdaptableHelper';
export class LayoutInternalApi extends ApiBase {
    /**
     * Compares 2 Layouts for equality
     * @param layout1 First Layout
     * @param layout2 Second Layout
     */
    areLayoutsEqual(layout1, layout2) {
        return areLayoutsEqual(layout1, layout2);
    }
    /**
     * Returns what the layout supports.
     * This takes into account the data-source.
     */
    getLayoutSupportedFeatures() {
        const layoutSupportedFeatures = {
            RowGroupedColumns: true,
            TableAggregationColumns: true,
            PivotAggregationColumns: true,
            PivotColumns: true,
            ColumnFilters: true,
            ColumnSorts: true,
            GridFilter: true,
            RowSummaries: true,
        };
        if (this.getGridApi().isTreeDataGrid()) {
            //  layoutSupportedFeatures.RowGroupedColumns = false;
            layoutSupportedFeatures.PivotColumns = false;
        }
        if (this.getGridApi().getAgGridRowModelType() === 'viewport') {
            layoutSupportedFeatures.RowGroupedColumns = false;
            layoutSupportedFeatures.TableAggregationColumns = false;
            layoutSupportedFeatures.PivotAggregationColumns = false;
            layoutSupportedFeatures.PivotColumns = false;
        }
        if (!this.getFilterOptions().useAdaptableFiltering) {
            layoutSupportedFeatures.ColumnFilters = false;
            layoutSupportedFeatures.GridFilter = false;
        }
        if (this.getEntitlementApi().getEntitlementAccessLevelForModule(ColumnFilterModuleId) == 'Hidden') {
            layoutSupportedFeatures.GridFilter = false;
        }
        if (this.getEntitlementApi().getEntitlementAccessLevelForModule(GridFilterModuleId) == 'Hidden') {
            layoutSupportedFeatures.GridFilter = false;
        }
        if (this._adaptable?.getAgGridRowModelType?.() !== 'clientSide') {
            layoutSupportedFeatures.RowSummaries = false;
        }
        return layoutSupportedFeatures;
    }
    hasLayoutSpecificObjects() {
        const layoutTagOptions = this.getLayoutOptions().layoutTagOptions;
        if (!layoutTagOptions) {
            return false;
        }
        if (layoutTagOptions.autoCheckTagsForLayouts == true ||
            typeof layoutTagOptions?.isObjectExtendedInLayout === 'function') {
            return true;
        }
        return false;
    }
    isObjectExtendedInLayout(object, module, layout) {
        if (!this.hasLayoutSpecificObjects()) {
            return true;
        }
        const layoutTagOptions = this.getLayoutOptions().layoutTagOptions;
        if (layoutTagOptions?.autoCheckTagsForLayouts == true) {
            return ArrayExtensions.IsNullOrEmpty(object.Tags) ? true : object.Tags?.includes(layout.Name);
        }
        const context = {
            adaptableObject: object,
            module,
            layout,
            ...this.getAdaptableInternalApi().buildBaseContext(),
        };
        return layoutTagOptions?.isObjectExtendedInLayout(context);
    }
    showLayoutNonExtendedObjects() {
        return this.getAdaptableState().Internal.Layout.showLayoutNonExtendedObjects;
    }
    isLayoutGrouped(layout) {
        if (!layout) {
            layout = this.getLayoutApi().getCurrentLayout();
        }
        return (layout?.RowGroupedColumns?.length || layout?.PivotGroupedColumns?.length) > 0;
    }
    setupRowSummaries() {
        if (!this._adaptable.agGridModulesAdapter.isAgGridModuleRegistered('PinnedRowModule')) {
            this.getAdaptableApi().consoleError(`Can NOT set Layout Row Summaries - missing required AG Grid module 'PinnedRowModule'`);
            return;
        }
        const rowSummaries = this.getAdaptableState().Internal?.RowSummary?.rowSummaries ?? [];
        const { top, bottom } = rowSummaries.reduce((acc, summaryRow) => {
            const row = summaryRow.RowData;
            if (summaryRow.Position === 'Bottom' || !summaryRow.Position) {
                acc.bottom.push(row);
            }
            else {
                acc.top.push(row);
            }
            return acc;
        }, { top: [], bottom: [] });
        const agGridAdapter = this.getAdaptableInternalApi().getAgGridAdapter();
        agGridAdapter.setGridOption('pinnedTopRowData', top);
        agGridAdapter.setGridOption('pinnedBottomRowData', bottom);
    }
    refreshLayout() {
        this._adaptable.refreshLayout();
    }
    getChangedColumnSorts(oldSorts, newSorts) {
        if (ArrayExtensions.IsNullOrEmpty(oldSorts) && ArrayExtensions.IsNullOrEmpty(newSorts)) {
            return [];
        }
        // If either one is empty but not both, all columns in the non-empty array have changed
        if (ArrayExtensions.IsNullOrEmpty(oldSorts)) {
            return newSorts.map((sort) => sort.ColumnId);
        }
        if (ArrayExtensions.IsNullOrEmpty(newSorts)) {
            return oldSorts.map((sort) => sort.ColumnId);
        }
        const changedColumnIds = [];
        // Create maps for quick lookup
        const oldSortsMap = new Map();
        oldSorts.forEach((sort) => {
            oldSortsMap.set(sort.ColumnId, sort.SortOrder);
        });
        // Check columns in new sorts that changed from old sorts
        newSorts.forEach((newSort) => {
            const oldSortOrder = oldSortsMap.get(newSort.ColumnId);
            // If column wasn't sorted before or sort order changed
            if (oldSortOrder === undefined || oldSortOrder !== newSort.SortOrder) {
                changedColumnIds.push(newSort.ColumnId);
            }
            // Remove processed columns from the map
            oldSortsMap.delete(newSort.ColumnId);
        });
        // Add remaining columns from old sorts (these were removed in new sorts)
        oldSortsMap.forEach((_, columnId) => {
            changedColumnIds.push(columnId);
        });
        return changedColumnIds;
    }
    buildInitialLayout(providedLayout, type) {
        const layoutType = type || (isPivotLayout(providedLayout) ? 'pivot' : 'table');
        const providedTableLayout = providedLayout;
        const providedPivotLayout = providedLayout;
        const initialEmptyLayout = layoutType === 'pivot'
            ? ObjectFactory.CreateEmptyPivotLayout({ ...providedPivotLayout })
            : ObjectFactory.CreateEmptyTableLayout({ ...providedTableLayout });
        const defaultLayoutProperties = this.getLayoutCreationDefaultProperties(layoutType);
        const initialLayout = {
            ...initialEmptyLayout,
            ...defaultLayoutProperties,
        };
        return initialLayout;
    }
    getLayoutCreationDefaultProperties(layoutType) {
        const layoutCreationDefPropsOption = this.getLayoutOptions().layoutCreationDefaultProperties;
        if (typeof layoutCreationDefPropsOption === 'object') {
            const initialProps = layoutType === 'table'
                ? layoutCreationDefPropsOption.tableLayout
                : layoutCreationDefPropsOption.pivotLayout;
            return initialProps;
        }
        if (typeof layoutCreationDefPropsOption === 'function') {
            const context = {
                layoutType,
                ...this.getAdaptableInternalApi().buildBaseContext(),
            };
            return layoutCreationDefPropsOption(context);
        }
        return {};
    }
    cloneLayout(layoutToClone) {
        let clonedLayout = Helper.cloneObject(layoutToClone);
        let result = {
            ...this.buildInitialLayout(clonedLayout),
        };
        result = AdaptableHelper.removeAdaptableObjectPrimitivesInlineDeep(result);
        delete result.Name;
        return result;
    }
    getCurrentLayout_perfOptimized() {
        // perf-optimized version of getCurrentLayout()
        const layoutState = this.getAdaptableState().Layout;
        const currentLayoutName = layoutState.CurrentLayout;
        if (!currentLayoutName) {
            return null;
        }
        return layoutState.Layouts.find((layout) => layout.Name === currentLayoutName);
    }
    getCurrentLayoutRowGroupDisplayType() {
        return this.getLayoutApi().getCurrentLayout()?.RowGroupDisplayType ?? 'single';
    }
    areAllGroupedColumnsFilterable() {
        const groupedAgColumns = this.getAgGridApi().getRowGroupColumns();
        let allHaveFilter = true;
        let allHaveFloatingFilter = true;
        for (const column of groupedAgColumns) {
            // Early exit: no need to continue if both are already false
            if (!allHaveFilter && !allHaveFloatingFilter) {
                break;
            }
            const colDef = column.getColDef();
            if (allHaveFilter && !colDef.filter) {
                allHaveFilter = false;
            }
            if (allHaveFloatingFilter && !colDef.floatingFilter) {
                allHaveFloatingFilter = false;
            }
        }
        return {
            filter: allHaveFilter,
            floatingFilter: allHaveFloatingFilter,
        };
    }
}
