"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.DataChangeHistoryGrid = void 0;
const tslib_1 = require("tslib");
const React = tslib_1.__importStar(require("react"));
const react_1 = require("react");
const AdaptableContext_1 = require("../AdaptableContext");
const usePrevious_1 = tslib_1.__importDefault(require("../../components/utils/usePrevious"));
const ModuleConstants_1 = require("../../Utilities/Constants/ModuleConstants");
const buildActionColumnButton_1 = require("./buildActionColumnButton");
const AdaptableAgGrid_1 = require("../../agGrid/AdaptableAgGrid");
const DataChangeHistoryGrid = (props) => {
    const { changeHistoryLog, adaptableContainerId, agGridContainerId, onUndoChange, onClearRow } = props;
    const mainAdaptableInstance = (0, AdaptableContext_1.useAdaptable)();
    const [_adaptableApi, setAdaptableApi] = (0, react_1.useState)(null);
    const adaptableApiRef = (0, react_1.useRef)(null);
    adaptableApiRef.current = _adaptableApi;
    const undoChangeEnabled = mainAdaptableInstance.api.entitlementApi.isModuleFullEntitlement(ModuleConstants_1.DataChangeHistoryModuleId);
    const previousChangeHistoryLog = (0, usePrevious_1.default)(changeHistoryLog, changeHistoryLog);
    // initialize Adaptable grid
    (0, react_1.useEffect)(() => {
        const initializeAdaptableGrid = async () => {
            const gridOptions = buildGridOptions(mainAdaptableInstance, changeHistoryLog);
            const adaptableOptions = buildAdaptableOptions(mainAdaptableInstance, adaptableContainerId, agGridContainerId, undoChangeEnabled, onUndoChange, onClearRow);
            const modules = mainAdaptableInstance.getAgGridRegisteredModules();
            const dataChangeHistoryAdaptableApi = await AdaptableAgGrid_1.AdaptableAgGrid._initInternal({
                variant: 'vanilla',
                adaptableOptions,
                gridOptions,
                modules,
            });
            setAdaptableApi(dataChangeHistoryAdaptableApi);
        };
        initializeAdaptableGrid();
        return () => {
            requestAnimationFrame(() => {
                adaptableApiRef.current?.internalApi
                    .getAdaptableInstance()
                    .destroy({ unmount: true, destroyAgGrid: true });
            });
        };
    }, []);
    // update row data
    (0, react_1.useEffect)(() => {
        const adaptableApi = adaptableApiRef.current;
        if (!adaptableApi) {
            // initial render
            return;
        }
        const addedChangeKeys = Object.keys(changeHistoryLog).filter((newChangeKey) => {
            const previousChangeWithSameKey = previousChangeHistoryLog[newChangeKey];
            if (!previousChangeWithSameKey) {
                return true;
            }
            const addedChange = changeHistoryLog[newChangeKey];
            return addedChange.changedAt !== previousChangeWithSameKey.changedAt;
        });
        const removedChangeKeys = Object.keys(previousChangeHistoryLog).filter((previousChangeKey) => {
            const newChangeWithSameKey = changeHistoryLog[previousChangeKey];
            if (!newChangeWithSameKey) {
                return true;
            }
            const previousChange = previousChangeHistoryLog[previousChangeKey];
            return previousChange.changedAt !== newChangeWithSameKey.changedAt;
        });
        const addedChangeHistoryLogs = filterChangeHistoryLog(changeHistoryLog, addedChangeKeys);
        const removedChangeHistoryLogs = filterChangeHistoryLog(previousChangeHistoryLog, removedChangeKeys);
        // here we access directly the AG Grid API, but this is OK because:
        // 1. this method (gridAPi.applyTransaction() is NOT accessible otherwise and making it public opens other cans of worms
        // 2. this UI will be reimplemented with Infinite Table anyway
        const addedRows = mapChangeHistoryRowData(addedChangeHistoryLogs, mainAdaptableInstance);
        const removedRows = mapChangeHistoryRowData(removedChangeHistoryLogs, mainAdaptableInstance);
        adaptableApi.agGridApi.applyTransactionAsync({
            add: addedRows,
            remove: removedRows,
        });
    }, [changeHistoryLog]);
    return React.createElement(React.Fragment, null);
};
exports.DataChangeHistoryGrid = DataChangeHistoryGrid;
const buildAdaptableOptions = (mainAdaptableInstance, adaptableContainerId, agGridContainerId, undoChangeEnabled, onUndoChange, onClearRow) => {
    const mainAdaptableOptions = mainAdaptableInstance.adaptableOptions;
    const mainAdaptableTheme = mainAdaptableInstance.api.themeApi.getCurrentTheme();
    const undoRowNode = (rowNode) => {
        const rowData = rowNode?.data;
        const changeKey = rowData?.['changeKey'];
        changeKey && onUndoChange(changeKey);
    };
    const clearRow = (rowNode) => {
        const rowData = rowNode?.data;
        const changeKey = rowData?.['changeKey'];
        changeKey && onClearRow(changeKey);
    };
    const actionColumnButton = (0, buildActionColumnButton_1.buildActionColumnButton)(mainAdaptableInstance.adaptableOptions?.dataChangeHistoryOptions, mainAdaptableInstance.api, undoRowNode, clearRow);
    let actionColumnOptions = undefined;
    if (actionColumnButton) {
        actionColumnOptions = {
            actionColumns: [
                {
                    columnId: 'undoActionColumn',
                    friendlyName: ' ',
                    rowScope: {
                        ExcludeGroupRows: true,
                        ExcludeSummaryRows: true,
                    },
                    actionColumnSettings: { suppressMenu: true, suppressMovable: true },
                    actionColumnButton,
                },
            ],
        };
    }
    const options = {
        primaryKey: 'primaryKey',
        licenseKey: mainAdaptableOptions.licenseKey,
        userName: `${mainAdaptableOptions.userName}`,
        adaptableId: `${mainAdaptableOptions.adaptableId}::DataChangeHistory`,
        containerOptions: {
            adaptableContainer: adaptableContainerId,
            agGridContainer: agGridContainerId,
        },
        entitlementOptions: {
            defaultAccessLevel: 'Hidden',
        },
        actionColumnOptions: actionColumnOptions,
        initialState: {
            Layout: {
                Revision: Date.now(),
                CurrentLayout: 'DataChangeHistoryLayout',
                Layouts: [
                    {
                        Name: 'DataChangeHistoryLayout',
                        TableColumns: [
                            'changeInfo.primaryKeyValue',
                            'changedColumnLabel',
                            'changeInfo.oldValue',
                            'changeInfo.newValue',
                            'changeInfo.changedAt',
                            'changeTriggerLabel',
                            'undoActionColumn',
                        ],
                        ColumnSorts: [
                            {
                                ColumnId: 'changeInfo.changedAt',
                                SortOrder: 'Desc',
                            },
                        ],
                        ColumnWidths: {
                            undoActionColumn: 110,
                        },
                        ColumnPinning: {
                            undoActionColumn: 'right',
                        },
                        AutoSizeColumns: true,
                    },
                ],
            },
            FormatColumn: {
                Revision: Date.now(),
                FormatColumns: [
                    {
                        Scope: {
                            ColumnIds: ['changeInfo.changedAt'],
                        },
                        DisplayFormat: {
                            Formatter: 'DateFormatter',
                            Options: {
                                Pattern: `${mainAdaptableOptions.userInterfaceOptions?.dateInputOptions?.dateFormat} HH:mm:ss`,
                            },
                        },
                    },
                ],
            },
            Theme: {
                Revision: Date.now(),
                CurrentTheme: mainAdaptableTheme,
            },
        },
    };
    if (!undoChangeEnabled) {
        const layoutColumns = options.initialState.Layout.Layouts[0].TableColumns;
        if (layoutColumns.includes('undoActionColumn')) {
            // remove action column from layout
            options.initialState.Layout.Layouts[0].TableColumns = layoutColumns.filter((columnId) => columnId !== 'undoActionColumn');
        }
    }
    return options;
};
const buildGridOptions = (mainAdaptableInstance, changeHistoryLog) => {
    const mainPrimaryKeyColumnHeader = mainAdaptableInstance.api.columnApi.getPrimaryKeyColumn()?.friendlyName ?? 'Row ID';
    const options = {
        loading: false,
        overlayNoRowsTemplate: '<div style="font-size: var(--ab-font-size-2);color: var(--ab-color-text-on-primary);">No Data Changes</div>',
        defaultColDef: {
            floatingFilter: true,
            filter: true,
            sortable: true,
            resizable: true,
            enableRowGroup: true,
            editable: false,
            enablePivot: false,
            enableValue: false,
            lockPinned: true,
            // default set to true to pass this to the action column
            suppressAutoSize: true,
            menuTabs: ['generalMenuTab', 'filterMenuTab'],
        },
        autoGroupColumnDef: {
            sortable: true,
        },
        columnDefs: [
            {
                field: 'primaryKey',
                cellDataType: 'text',
                hide: true,
            },
            {
                headerName: `Row (${mainPrimaryKeyColumnHeader})`,
                field: 'changeInfo.primaryKeyValue',
                cellDataType: 'text',
                suppressAutoSize: false,
                flex: 3,
                initialFlex: 3,
            },
            {
                headerName: 'Column',
                field: 'changedColumnLabel',
                cellDataType: 'text',
                suppressAutoSize: false,
                flex: 3,
                initialFlex: 3,
            },
            {
                headerName: 'Previous',
                field: 'changeInfo.oldValue',
                cellDataType: 'text',
                suppressAutoSize: false,
                flex: 3,
                initialFlex: 3,
            },
            {
                headerName: 'New',
                field: 'changeInfo.newValue',
                cellDataType: 'text',
                suppressAutoSize: false,
                flex: 3,
                initialFlex: 3,
            },
            {
                headerName: 'Changed',
                field: 'changeInfo.changedAt',
                cellDataType: 'date',
                suppressAutoSize: false,
                flex: 3,
                initialFlex: 3,
            },
            {
                headerName: 'Source',
                field: 'changeTriggerLabel',
                cellDataType: 'text',
                suppressAutoSize: false,
                flex: 2,
                initialFlex: 2,
            },
        ],
        rowData: mapChangeHistoryRowData(changeHistoryLog, mainAdaptableInstance),
        cellSelection: true,
        suppressColumnVirtualisation: false,
        sideBar: false,
        rowSelection: {
            mode: 'multiRow',
        },
        skipHeaderOnAutoSize: true,
    };
    return options;
};
const mapChangeHistoryRowData = (changeHistoryLog = {}, mainAdaptableInstance) => {
    return Object.entries(changeHistoryLog).map(([changeKey, changeInfo]) => {
        return {
            primaryKey: `${changeKey}::${changeInfo.changedAt}`,
            changeKey,
            changeTriggerLabel: getChangeTriggerLabel(changeInfo),
            changedColumnLabel: getColumnHeaderLabel(changeInfo.column.columnId, mainAdaptableInstance),
            changeInfo,
        };
    });
};
// memoize headers to avoid unnecessary main grid lookups
const headerMap = new Map();
const getColumnHeaderLabel = (columnId, mainAdaptableInstance) => {
    if (!headerMap.has(columnId)) {
        headerMap.set(columnId, mainAdaptableInstance.api.columnApi.getColumnWithColumnId(columnId)?.friendlyName ?? columnId);
    }
    return headerMap.get(columnId);
};
const getChangeTriggerLabel = (changeInfo) => {
    return changeInfo.trigger === 'tick' ? 'Ticking' : 'User Edit';
};
const filterChangeHistoryLog = (changeObject, filterValues) => {
    const result = {};
    filterValues.forEach((allowedKey) => {
        result[allowedKey] = changeObject[allowedKey];
    });
    return result;
};
