import * as LayoutRedux from '../../Redux/ActionsReducers/LayoutRedux';
import * as ModuleConstants from '../../Utilities/Constants/ModuleConstants';
import { ApiBase } from './ApiBase';
import StringExtensions from '../../Utilities/Extensions/StringExtensions';
import { createUuid } from '../../AdaptableState/Uuid';
import { PopupShowPrompt } from '../../Redux/ActionsReducers/PopupRedux';
import { LayoutInternalApi } from '../Internal/LayoutInternalApi';
import { isPivotLayout, normalizeLayout } from './LayoutHelpers';
import { ERROR_LAYOUT } from '../../Utilities/Constants/GeneralConstants';
export class LayoutApiImpl extends ApiBase {
    constructor(_adaptable) {
        super(_adaptable);
        this.internalApi = new LayoutInternalApi(_adaptable);
    }
    updateCurrentLayout(updateFn) {
        const currentLayout = this.getCurrentLayout();
        const updatedLayout = normalizeLayout(updateFn(structuredClone(currentLayout)));
        this.createOrUpdateLayout(updatedLayout);
    }
    isCurrentLayoutPivot() {
        return isPivotLayout(this.getCurrentLayout());
    }
    getLayoutState() {
        return this.getAdaptableState().Layout;
    }
    getCurrentVisibleColumnIdsMapForTableLayout() {
        const layout = this.getCurrentLayout();
        if (isPivotLayout(layout)) {
            return {};
        }
        return layout.TableColumns.reduce((acc, colId) => {
            acc[colId] = true;
            return acc;
        }, {});
    }
    getCurrentVisibleColumnIdsForTableLayout() {
        const layout = this.getCurrentLayout();
        if (isPivotLayout(layout)) {
            return [];
        }
        return layout.TableColumns.filter((colId) => !layout.ColumnVisibility || layout.ColumnVisibility?.[colId] !== false);
    }
    getCurrentVisibleColumnIdsForPivotLayout() {
        const layout = this.getCurrentLayout();
        if (!isPivotLayout(layout)) {
            return [];
        }
        return this.getAgGridApi()
            .getAllDisplayedColumns()
            .map((col) => col.getColId());
    }
    getCurrentRowGroupsColumnIds() {
        const layout = this.getCurrentLayout();
        if (isPivotLayout(layout)) {
            return layout.PivotGroupedColumns;
        }
        return layout.RowGroupedColumns;
    }
    setLayout(layoutName) {
        if (StringExtensions.IsNullOrEmpty(layoutName)) {
            return;
        }
        if (layoutName === this.getCurrentLayoutName()) {
            return;
        }
        let layout = this.getLayoutByName(layoutName);
        if (this.checkItemExists(layout, layoutName, 'Layout')) {
            this.dispatchAction(LayoutRedux.LayoutSelect(layoutName));
        }
    }
    getCurrentLayout() {
        let layoutName = this.getLayoutState().CurrentLayout;
        return this.getLayoutByName(layoutName) ?? ERROR_LAYOUT;
    }
    getCurrentLayoutColumnSort(columnId) {
        const currentLayout = this.getCurrentLayout();
        return (currentLayout?.ColumnSorts?.find?.((sort) => sort.ColumnId === columnId)?.SortOrder ?? null);
    }
    getCurrentLayoutName() {
        return this.getAdaptableState().Layout.CurrentLayout;
    }
    getLayoutByName(layoutName) {
        if (StringExtensions.IsNotNullOrEmpty(layoutName)) {
            let layout = this.getLayouts().find((l) => l.Name == layoutName);
            if (this.checkItemExists(layout, layoutName, 'Layout')) {
                return layout;
            }
        }
    }
    createOrUpdateExtendedLayout(extendedLayoutInfo) {
        const config = {
            includeLayoutNotExtendedObjects: true,
        };
        // Alerts
        const alertExtensions = extendedLayoutInfo.Extensions.filter((e) => {
            return e.Module == 'Alert';
        });
        alertExtensions.forEach((le) => {
            const alertDefinition = le.Object;
            const existingAlertDefinition = this.getAlertApi().getAlertDefinitionById(alertDefinition.Uuid, config);
            if (!existingAlertDefinition) {
                this.getAlertApi().addAlertDefinition(alertDefinition);
            }
        });
        // Custom Sorts
        const customSortExtensions = extendedLayoutInfo.Extensions.filter((e) => {
            return e.Module == 'CustomSort';
        });
        customSortExtensions.forEach((le) => {
            const customSort = le.Object;
            const existingCustomSort = this.getCustomSortApi().getCustomSortById(customSort.Uuid, config);
            if (!existingCustomSort) {
                this.getCustomSortApi().addCustomSort(customSort);
            }
        });
        // Flashing Cells
        const flashingCellExtensions = extendedLayoutInfo.Extensions.filter((e) => {
            return e.Module == 'FlashingCell';
        });
        flashingCellExtensions.forEach((le) => {
            const flashingCellDefinition = le.Object;
            const existingflashingCellDefinition = this.getFlashingCellApi().getFlashingCellDefinitionById(flashingCellDefinition.Uuid, config);
            if (!existingflashingCellDefinition) {
                this.getFlashingCellApi().addFlashingCellDefinition(flashingCellDefinition);
            }
        });
        // FormatColumns
        const formatColumnExtensions = extendedLayoutInfo.Extensions.filter((e) => {
            return e.Module == 'FormatColumn';
        });
        formatColumnExtensions.forEach((le) => {
            const formatColumn = le.Object;
            const existingFormatColumn = this.getFormatColumnApi().getFormatColumnByUuId(formatColumn.Uuid, config);
            if (!existingFormatColumn) {
                this.getFormatColumnApi().addFormatColumn(formatColumn);
            }
        });
        // Plus Minus
        const plusMinusExtensions = extendedLayoutInfo.Extensions.filter((e) => {
            return e.Module == 'PlusMinus';
        });
        plusMinusExtensions.forEach((le) => {
            const plusMinusNudge = le.Object;
            const existingPlusMinusNudge = this.getPlusMinusApi().getPlusMinusById(plusMinusNudge.Uuid, config);
            if (!existingPlusMinusNudge) {
                this.getPlusMinusApi().addPlusMinusNudge(plusMinusNudge);
            }
        });
        // Schedule
        const scheduleExtensions = extendedLayoutInfo.Extensions.filter((e) => {
            return e.Module == 'Schedule';
        });
        scheduleExtensions.forEach((le) => {
            const schedule = le.Object;
            const existingSchedule = this.getScheduleApi().getScheduleById(schedule.Uuid, config);
            if (!existingSchedule) {
                if (existingSchedule.ScheduleType == 'Reminder') {
                    this.getScheduleApi().addReminderSchedule(schedule);
                }
                if (existingSchedule.ScheduleType == 'Report') {
                    this.getScheduleApi().addReportSchedule(schedule);
                }
            }
        });
        // Shortcut
        const shortCutExtensions = extendedLayoutInfo.Extensions.filter((e) => {
            return e.Module == 'Shortcut';
        });
        shortCutExtensions.forEach((le) => {
            const shortcut = le.Object;
            const existingShortcut = this.getShortcutApi().getShortcutById(shortcut.Uuid, config);
            if (!existingShortcut) {
                this.getShortcutApi().addShortcut(shortcut);
            }
        });
        // StyledColumn
        const styledColumnExtensions = extendedLayoutInfo.Extensions.filter((e) => {
            return e.Module == 'StyledColumn';
        });
        styledColumnExtensions.forEach((le) => {
            const styledColumn = le.Object;
            const existingStyledColumn = this.getStyledColumnApi().getStyledColumnById(styledColumn.Uuid, config);
            if (!existingStyledColumn) {
                this.getStyledColumnApi().addStyledColumn(styledColumn);
            }
        });
        this.createOrUpdateLayout(extendedLayoutInfo.Layout);
    }
    getExtendedLayoutByName(layoutName) {
        const layout = this.getLayoutByName(layoutName);
        if (!layout) {
            return undefined;
        }
        const config = {
            includeLayoutNotExtendedObjects: false,
            extendedLayoutName: layoutName,
        };
        // cannot see a better way than to go through this module by module...
        let extensions = [];
        this.getAlertApi()
            .getAlertDefinitions(config)
            .forEach((obj) => {
            extensions.push({ Module: 'Alert', Object: obj });
        });
        this.getCustomSortApi()
            .getCustomSorts(config)
            .forEach((obj) => {
            extensions.push({ Module: 'CustomSort', Object: obj });
        });
        this.getFlashingCellApi()
            .getFlashingCellDefinitions(config)
            .forEach((obj) => {
            extensions.push({ Module: 'FlashingCell', Object: obj });
        });
        this.getFormatColumnApi()
            .getFormatColumns(config)
            .forEach((obj) => {
            extensions.push({ Module: 'FormatColumn', Object: obj });
        });
        this.getPlusMinusApi()
            .getAllPlusMinus(config)
            .forEach((obj) => {
            extensions.push({ Module: 'PlusMinus', Object: obj });
        });
        this.getScheduleApi()
            .getReminderSchedules(config)
            .forEach((obj) => {
            extensions.push({ Module: 'Schedule', Object: obj });
        });
        this.getShortcutApi()
            .getShortcuts(config)
            .forEach((obj) => {
            extensions.push({ Module: 'Shortcut', Object: obj });
        });
        this.getStyledColumnApi()
            .getStyledColumns(config)
            .forEach((obj) => {
            extensions.push({ Module: 'StyledColumn', Object: obj });
        });
        return {
            Layout: layout,
            Extensions: extensions,
        };
    }
    getLayouts() {
        return this.getAdaptableState().Layout.Layouts ?? [];
    }
    getLayoutById(id) {
        return this.getLayouts()?.find((layout) => layout?.Uuid === id);
    }
    saveCurrentLayout() {
        let currentLayout = this.getCurrentLayout();
        if (currentLayout) {
            this.createOrUpdateLayout(currentLayout);
        }
    }
    doesLayoutExist(layout) {
        if (layout == null) {
            return false;
        }
        let existingLayout = this.getLayouts().find((l) => l.Uuid == layout.Uuid || l.Name === layout.Name);
        return existingLayout != null;
    }
    createAndSetLayout(layoutToCreate) {
        const layout = this.createLayout(layoutToCreate);
        if (layout) {
            this.setLayout(layoutToCreate.Name);
        }
        return layout;
    }
    createLayout(layoutToCreate) {
        if (this.doesLayoutExist(layoutToCreate)) {
            this.logError("Cannot create layout with the Name: '" + layoutToCreate.Name + "' as it already exists");
            return false;
        }
        const newLayout = this.internalApi.buildInitialLayout(layoutToCreate);
        this.addUidToAdaptableObject(newLayout);
        this.dispatchAction(LayoutRedux.LayoutAdd(newLayout));
        return newLayout;
    }
    cloneAndSetLayout(layoutToClone, layoutName) {
        const newLayout = this.cloneLayout(layoutToClone, layoutName);
        if (newLayout) {
            this.setLayout(layoutName);
        }
        return newLayout;
    }
    cloneLayout(layoutToClone, layoutName) {
        if (!this.doesLayoutExist(layoutToClone)) {
            this.logError("Cannot clone layout with Name: '" + layoutName + "' as other Layout does not exist");
            return false;
        }
        const newLayout = {
            ...this.internalApi.cloneLayout(layoutToClone),
            Name: layoutName,
            Uuid: createUuid(),
        };
        this.dispatchAction(LayoutRedux.LayoutAdd(newLayout));
        return this.getLayoutById(newLayout.Uuid);
    }
    setColumnCaption(columnId, caption) {
        if (StringExtensions.IsNotNullOrEmpty(columnId) && StringExtensions.IsNotNullOrEmpty(caption)) {
            this.updateCurrentLayout((layout) => {
                layout.ColumnHeaders = { ...layout.ColumnHeaders };
                layout.ColumnHeaders[columnId] = caption;
                return layout;
            });
        }
    }
    createOrUpdateLayout(layout) {
        if (!this.doesLayoutExist(layout)) {
            this.createLayout(layout);
        }
        else {
            this.dispatchAction(LayoutRedux.LayoutSave(layout));
        }
    }
    showChangeColumnCaption(column) {
        const currentLayout = this.getCurrentLayout();
        const customHeader = currentLayout.ColumnHeaders?.[column.columnId] ?? column.friendlyName;
        this.dispatchAction(PopupShowPrompt({
            Header: `Change caption for '${column.friendlyName}'`,
            Msg: '',
            DefaultValue: customHeader,
            ConfirmActionCreator: (inputText) => {
                if (inputText !== customHeader) {
                    this.setColumnCaption(column.columnId, inputText);
                }
                return { type: 'NOOP' };
            },
        }));
    }
    openLayoutSettingsPanel() {
        this.showModulePopup(ModuleConstants.LayoutModuleId);
    }
    showLayoutEditor(layoutName, layoutType, action = 'Edit') {
        let preparedAction = action;
        if (!['Edit', 'New', 'Clone'].includes(action)) {
            preparedAction = 'Edit';
            this.logError(`When opening the layout editor the action must be one of: New, Clone, Edit; given: ${action}`);
        }
        let layout = layoutName ? this.getLayoutByName(layoutName) : this.getCurrentLayout();
        if (preparedAction === 'New') {
            layout = null;
        }
        this.showModulePopup(ModuleConstants.LayoutModuleId, {
            source: 'Toolbar',
            action: preparedAction,
            value: layout,
            config: {
                layoutType,
            },
        });
    }
    deleteLayout(layout) {
        const layoutCount = this.getLayouts().length;
        if (layoutCount === 1) {
            this.logWarn('You cannot delete the only Layout.  AdapTable always requires one layout');
            return;
        }
        this.dispatchAction(LayoutRedux.LayoutDelete(layout));
    }
    deleteLayoutByName(layoutName) {
        const layout = this.getLayoutByName(layoutName);
        if (!layout) {
            this.logWarn('No Layout exists with that name');
            return;
        }
        return this.deleteLayout(layout);
    }
    removeColumnFromCurrentLayout(columnId) {
        const column = this.getColumnApi().getColumnWithColumnId(columnId);
        if (column) {
            const layout = this.getCurrentLayout();
            if (!isPivotLayout(layout)) {
                this.updateCurrentLayout((layout) => {
                    layout.TableColumns = layout.TableColumns.filter((c) => c !== columnId);
                    return layout;
                });
            }
            else {
                this.updateCurrentLayout((layout) => {
                    layout.PivotColumns = layout.PivotColumns.filter((c) => c !== columnId);
                    return layout;
                });
            }
        }
    }
    addColumnToCurrentLayout(columnId) {
        const column = this.getColumnApi().getColumnWithColumnId(columnId);
        if (column) {
            const layout = this.getCurrentLayout();
            if (!isPivotLayout(layout)) {
                this.updateCurrentLayout((layout) => {
                    layout.TableColumns.push(columnId);
                    return layout;
                });
            }
            else {
                this.updateCurrentLayout((layout) => {
                    layout.PivotColumns.push(columnId);
                    return layout;
                });
            }
        }
    }
}
