import * as React from 'react';
import FormLayout, { FormRow } from '../../components/FormLayout';
import Panel from '../../components/Panel';
import { useAdaptable } from '../AdaptableContext';
import { ColumnSelector } from '../Components/Selectors/ColumnSelector';
import { AdaptableAgGrid } from '../../agGrid/AdaptableAgGrid';
import { Box, Flex } from '../../components/Flex';
import { ExportModuleId } from '../../Utilities/Constants/ModuleConstants';
import StringExtensions from '../../Utilities/Extensions/StringExtensions';
const ADAPTABLE_CONTAINER_ID = 'transposed-adaptable-container';
const AG_GRID_CONTAINER_ID = 'transposed-adaptable-ag-grid-container';
/** Field used for the first column in transposed grid (hidden, holds column id). */
const TRANSPOSED_FIRST_COLUMN_FIELD = '_transposed_column_value';
/** Header used for the first visible column in transposed grid (shows friendly name). */
const TRANSPOSED_FIRST_COLUMN_HEADER = '_transposed_column_header';
function buildTransposedAdaptableOptions({ hostOptions, transposedRowsAndColumns, currentTheme, }) {
    return {
        primaryKey: TRANSPOSED_FIRST_COLUMN_FIELD,
        licenseKey: hostOptions.licenseKey,
        userName: `${hostOptions.userName}`,
        adaptableId: `${hostOptions.adaptableId}::TransposedView`,
        containerOptions: {
            adaptableContainer: ADAPTABLE_CONTAINER_ID,
            agGridContainer: AG_GRID_CONTAINER_ID,
        },
        entitlementOptions: { defaultAccessLevel: 'Hidden' },
        initialState: {
            Layout: {
                Revision: Date.now(),
                CurrentLayout: 'TransposedView',
                Layouts: [
                    {
                        Name: 'TransposedView',
                        TableColumns: [
                            TRANSPOSED_FIRST_COLUMN_HEADER,
                            ...transposedRowsAndColumns.transposedColumns.map((c) => c.colId),
                        ],
                        ColumnPinning: { [TRANSPOSED_FIRST_COLUMN_HEADER]: 'left' },
                        AutoSizeColumns: true,
                    },
                ],
            },
            Theme: { CurrentTheme: currentTheme },
        },
    };
}
function buildTransposedGridOptions({ transposedRowsAndColumns, elevatedColumnId, adaptableApi, }) {
    const firstColumn = {
        field: TRANSPOSED_FIRST_COLUMN_HEADER,
        headerName: adaptableApi.columnApi.getFriendlyNameForColumnId(elevatedColumnId),
    };
    return {
        loading: false,
        defaultColDef: {
            floatingFilter: false,
            filter: false,
            sortable: true,
            resizable: true,
            enableRowGroup: false,
            editable: false,
            enablePivot: false,
            enableValue: false,
            lockPinned: true,
            menuTabs: [],
            width: 120,
        },
        columnDefs: [
            { field: TRANSPOSED_FIRST_COLUMN_FIELD, hide: true },
            firstColumn,
            ...transposedRowsAndColumns.transposedColumns.map((col) => ({ field: col.colId, headerName: col.header })),
        ],
        rowData: transposedRowsAndColumns.transposedRows,
        sideBar: false,
    };
}
export const TransposedPopup = (props) => {
    const adaptable = useAdaptable();
    const primaryKey = adaptable.api.optionsApi.getPrimaryKey();
    const rawConfig = (props.popupProps ?? {});
    const transposeConfig = {
        transposedColumnId: rawConfig.transposedColumnId ?? primaryKey,
        hideTransposedColumn: rawConfig.hideTransposedColumn ?? true,
        autosize: rawConfig.autosize ?? true,
        columnsToTranspose: rawConfig.columnsToTranspose,
        rowsToTranspose: rawConfig.rowsToTranspose,
    };
    const rowNodes = React.useMemo(() => {
        let transposableRowNodes = [];
        const rowsToTranspose = transposeConfig.rowsToTranspose;
        if (rowsToTranspose === 'VisibleOnly') {
            return adaptable.api.gridApi.getVisibleRowNodes();
        }
        if (rowsToTranspose === 'All') {
            return adaptable.api.gridApi.getAllRowNodes();
        }
        if (StringExtensions.IsNotNullOrEmpty(rowsToTranspose)) {
            adaptable.api.gridApi.getAllRowNodes().forEach((rn) => {
                const shouldTransposeRow = adaptable.api.internalApi
                    .getQueryLanguageService()
                    .evaluateBooleanExpression(rowsToTranspose, ExportModuleId, rn);
                if (shouldTransposeRow) {
                    transposableRowNodes.push(rn);
                }
            });
            return transposableRowNodes;
        }
        return adaptable.api.gridApi.getAllRowNodes();
    }, [transposeConfig.rowsToTranspose, adaptable.api]);
    const [elevatedColumnId, setElevatedColumnIdState] = React.useState(() => transposeConfig.transposedColumnId ?? primaryKey);
    const setElevatedColumnId = (newElevatedColumnId) => {
        transposedAdaptableApiRef.current?.destroy({ unmount: true, destroyAgGrid: true });
        setElevatedColumnIdState(newElevatedColumnId);
    };
    const transposedAdaptableApiRef = React.useRef(null);
    const columns = React.useMemo(() => {
        const allUIColumns = adaptable.api.columnApi.getUIAvailableColumns();
        const columnsToTranspose = transposeConfig.columnsToTranspose;
        if (!columnsToTranspose) {
            return allUIColumns;
        }
        const columnIds = typeof columnsToTranspose === 'function'
            ? columnsToTranspose({
                ...adaptable.api.internalApi.buildBaseContext(),
                columns: allUIColumns,
            })
            : columnsToTranspose;
        return columnIds
            .map((c) => adaptable.api.columnApi.getColumnWithColumnId(c))
            .filter((col) => col != null);
    }, [transposeConfig.columnsToTranspose, adaptable.api]);
    /**
     * Build transposed structure: original rows become columns (colId = primaryKey value),
     * original columns become rows. Each transposed row has the column id/header plus
     * one cell per original row keyed by primaryKey value.
     */
    const transposedRowsAndColumns = React.useMemo(() => {
        const transposedColumns = [];
        const transposedRows = [];
        for (const row of rowNodes) {
            const colId = adaptable.api.gridApi.getNormalisedValueFromRowNode(row, primaryKey) + '';
            const header = adaptable.api.gridApi.getNormalisedValueFromRowNode(row, elevatedColumnId) + '';
            transposedColumns.push({ colId, header });
        }
        for (const column of columns) {
            if (transposeConfig.hideTransposedColumn &&
                column.columnId === elevatedColumnId) {
                continue;
            }
            const transposedRow = {
                [TRANSPOSED_FIRST_COLUMN_FIELD]: column.columnId,
                [TRANSPOSED_FIRST_COLUMN_HEADER]: column.friendlyName,
            };
            for (const row of rowNodes) {
                const key = adaptable.api.gridApi.getNormalisedValueFromRowNode(row, primaryKey);
                let value = adaptable.api.gridApi.getDisplayValueFromRowNode(row, column.columnId);
                if (value instanceof Date) {
                    value = value.toLocaleString();
                }
                transposedRow[key] = value;
            }
            transposedRows.push(transposedRow);
        }
        return { transposedColumns, transposedRows };
    }, [rowNodes, primaryKey, elevatedColumnId, columns, transposeConfig.hideTransposedColumn, adaptable.api]);
    React.useEffect(() => {
        const hostOptions = adaptable.adaptableOptions;
        const adaptableOptions = buildTransposedAdaptableOptions({
            hostOptions,
            transposedRowsAndColumns,
            currentTheme: adaptable.api.themeApi.getCurrentTheme(),
        });
        const gridOptions = buildTransposedGridOptions({
            transposedRowsAndColumns,
            elevatedColumnId,
            adaptableApi: adaptable.api,
        });
        const modules = adaptable.agGridModulesAdapter.getAgGridRegisteredModules();
        AdaptableAgGrid._initInternal({
            variant: 'vanilla',
            adaptableOptions,
            gridOptions,
            modules,
        }).then((adaptableApi) => {
            transposedAdaptableApiRef.current = adaptableApi;
            adaptableApi.eventApi.on('ThemeChanged', (event) => {
                transposedAdaptableApiRef.current?.themeApi.loadTheme(typeof event.theme === 'object' ? event.theme.Name : event.theme);
            });
        });
    }, [elevatedColumnId, adaptable]);
    React.useEffect(() => {
        return () => {
            requestAnimationFrame(() => {
                transposedAdaptableApiRef.current?.destroy({ unmount: true, destroyAgGrid: true });
            });
        };
    }, []);
    return (React.createElement(Flex, { flexDirection: "column", className: "twa:w-full twa:h-full" },
        React.createElement(Panel, null,
            React.createElement(FormLayout, null,
                React.createElement(FormRow, { label: "Elevated Column" },
                    React.createElement(ColumnSelector, { value: elevatedColumnId, onChange: setElevatedColumnId })))),
        React.createElement(Flex, { className: "twa:h-full" },
            React.createElement(Box, { id: ADAPTABLE_CONTAINER_ID }),
            React.createElement(Box, { className: "twa:h-full twa:w-full", id: AG_GRID_CONTAINER_ID }))));
};
