import * as React from 'react';
import { renderWithAdaptableContext } from '../View/renderWithAdaptableContext';
import { AdaptableFloatingFilter } from '../View/Components/ColumnFilter/AdaptableFloatingFilter';
const filterContainerStyle = {
    overflow: 'hidden',
    minWidth: '0',
    height: '100%',
    display: 'flex',
    alignItems: 'stretch',
    position: 'relative',
    flex: '1 1 auto',
};
export const AgGridFloatingFilterAdapterFactory = (adaptable) => {
    const adaptableApi = adaptable.api;
    function getContainerId(colId) {
        return `floatingFilter_${colId}_${adaptable.adaptableOptions.adaptableId}`;
    }
    function getFilterProps(colId) {
        const column = adaptableApi.columnApi.getColumnWithColumnId(colId);
        const columnFilterProps = {
            Column: column,
            Adaptable: adaptable,
            ShowCloseButton: false,
        };
        return columnFilterProps;
    }
    function findParentWithClass(element, className, stopClasses, applyToAll) {
        let current = element.parentElement;
        while (current) {
            // Stop traversing if we hit any of the stop classes
            if (stopClasses.some((stopClass) => current.classList.contains(stopClass))) {
                return null;
            }
            if (current.classList.contains(className)) {
                return current;
            }
            applyToAll?.(current);
            current = current.parentElement;
        }
        return null;
    }
    function patchParentElement(filterContainer) {
        if (!filterContainer) {
            return;
        }
        const stopClasses = ['ag-header-row', 'ag-header-row-column-filter'];
        // Find and update floating filter body
        const filterBody = findParentWithClass(filterContainer, 'ag-floating-filter-full-body', stopClasses, (currentElem) => {
            currentElem.style.height = '100%';
        });
        if (filterBody) {
            filterBody.style.overflow = 'visible';
        }
        // Find and update header cell
        const headerCell = findParentWithClass(filterContainer, 'ag-header-cell', stopClasses);
        if (headerCell?.classList.contains('ag-floating-filter')) {
            headerCell.style.padding = 'var(--ab-space-1)';
        }
    }
    if (adaptable.isAgGridInitialising) {
        if (adaptable.variant === 'react') {
            return () => React.createElement(React.Fragment, null);
        }
        return class FloatingFilterStub {
            init(params) {
                this.filterContainer = document.createElement('div');
            }
            getGui() {
                return this.filterContainer;
            }
            destroy() {
                this.unmountReactRoot?.();
                this.filterContainer = null;
            }
            onParentModelChanged() {
                // nothing yet
            }
        };
    }
    return class AgGridFloatingFilterAdapter {
        init(params) {
            const colId = params.column.getColId();
            this.colId = colId;
            this.filterContainer = document.createElement('div');
            this.filterContainer.id = getContainerId(colId);
            Object.keys(filterContainerStyle).forEach((key) => {
                //@ts-ignore
                this.filterContainer.style[key] = filterContainerStyle[key];
            });
            const column = adaptableApi.columnApi.getColumnWithColumnId(colId);
            if (column) {
                const filterProps = getFilterProps(colId);
                this.unmountReactRoot = adaptable.renderReactRoot(renderWithAdaptableContext(React.createElement(AdaptableFloatingFilter, {
                    ...filterProps,
                }), adaptable), this.filterContainer);
            }
        }
        onParentModelChanged(parentModel, filterChangedEvent) {
            // AFL: this should NOT be required, but AG Grid calls this method
            // most likely is a bug and will be removed in future versions
        }
        afterGuiAttached() {
            patchParentElement(this.filterContainer);
        }
        getGui() {
            return this.filterContainer;
        }
        refresh(params) {
            // always reuse the current instance
            // the filte ris refreshed in the underlying React component
            return true;
        }
        destroy() {
            // Use setTimeout to defer unmounting to next event loop tick
            // This ensures we're not unmounting during React's rendering phase
            if (this.unmountReactRoot) {
                const unmount = this.unmountReactRoot;
                setTimeout(() => {
                    unmount();
                }, 0);
                this.unmountReactRoot = undefined;
            }
            this.filterContainer = null;
        }
    };
};
