import React, { useState, useMemo, useCallback, createContext } from 'react';
import { getStickyColumnStyle, CELL_PADDING, CELL_EDGE_PADDING, } from '../DataTable/DataTable.utils';
const MIN_COLUMN_WIDTH = 60;
const parseColumnWidth = (width) => {
    if (!width)
        return MIN_COLUMN_WIDTH;
    if (typeof width === 'number') {
        return width;
    }
    if (typeof width === 'string') {
        if (width.endsWith('px')) {
            const parsed = parseInt(width, 10);
            return isNaN(parsed) ? MIN_COLUMN_WIDTH : parsed;
        }
        if (width.endsWith('%')) {
            return width;
        }
        const parsed = parseInt(width, 10);
        return isNaN(parsed) ? MIN_COLUMN_WIDTH : parsed;
    }
    return MIN_COLUMN_WIDTH;
};
const createDefaultContext = () => ({
    columnWidths: null,
    getEffectiveColumnWidth: (column) => column.width,
    // default handling of sticky columns style is the exsisting util
    getStickyColumnStyle: (columns, column) => {
        return getStickyColumnStyle(columns, column);
    },
    getTableWidth: (fallback) => fallback || '100%',
    resizeColumn: () => { },
});
export const ColumnResizeContext = createContext(createDefaultContext());
/**
 * ColumnResize manages the state and logic of column resizing for tables.
 * Given an array of columns with resize configuration, it provides a context with resize handlers,
 * width calculations, and sticky column positioning.
 *
 * Key features:
 * - Manages column width state with min/max constraints
 * - Provides effective width calculations for columns
 * - Handles sticky column positioning with dynamic widths
 * - Supports both resizable and non-resizable table modes
 * - Offers resize event callbacks (onColumnResize, onColumnResizeStart, onColumnResizeEnd)
 */
export const ColumnResize = ({ columns = [], isTableResizable = false, onColumnResize, onColumnResizeStart, onColumnResizeEnd, minColumnWidth = MIN_COLUMN_WIDTH, maxColumnWidth, children, }) => {
    const initializeColumnWidths = () => {
        if (!isTableResizable) {
            return null;
        }
        // Resizable flow: Parse all widths to numbers, store in mapping
        return columns.reduce((acc, column) => {
            const id = column.resizeProps?.id;
            if (id) {
                const parsedWidth = parseColumnWidth(column.width);
                if (typeof parsedWidth === 'number') {
                    acc[id] = parsedWidth;
                }
            }
            return acc;
        }, {});
    };
    const [columnWidths, setColumnWidths] = useState(initializeColumnWidths);
    const getEffectiveColumnWidth = useCallback((column) => {
        if (isTableResizable && columnWidths) {
            const id = column.resizeProps?.id?.toString();
            if (id && columnWidths[id]) {
                return columnWidths[id];
            }
            return parseColumnWidth(column.width);
        }
        return column.width;
    }, [isTableResizable, columnWidths]);
    const getStickyColumnStyle = useCallback((columns, column) => {
        let left = 0;
        for (let i = 0; i < columns.length; i++) {
            const col = columns[i];
            if (col === column) {
                break;
            }
            const horizontalPadding = i === 0 ? CELL_EDGE_PADDING + CELL_PADDING : 2 * CELL_PADDING;
            const effectiveWidth = getEffectiveColumnWidth(col);
            const widthValue = typeof effectiveWidth === 'string'
                ? parseInt(effectiveWidth, 10)
                : effectiveWidth;
            left += (widthValue ?? MIN_COLUMN_WIDTH) + horizontalPadding;
        }
        return { left };
    }, [getEffectiveColumnWidth]);
    const handleColumnResize = useCallback((columnId, newWidth) => {
        if (!isTableResizable || !columnWidths) {
            return;
        }
        let clampedWidth = newWidth;
        if (minColumnWidth !== undefined && newWidth < minColumnWidth) {
            clampedWidth = minColumnWidth;
        }
        if (maxColumnWidth !== undefined && newWidth > maxColumnWidth) {
            clampedWidth = maxColumnWidth;
        }
        setColumnWidths(prevState => {
            if (!prevState) {
                return prevState;
            }
            const updatedColumnWidths = {
                ...prevState,
                [columnId]: clampedWidth,
            };
            return updatedColumnWidths;
        });
        if (onColumnResize) {
            onColumnResize(columnId, clampedWidth);
        }
    }, [
        isTableResizable,
        columnWidths,
        minColumnWidth,
        maxColumnWidth,
        onColumnResize,
    ]);
    const handleColumnResizeStart = useCallback((columnId, e) => {
        if (onColumnResizeStart && columnWidths) {
            onColumnResizeStart(columnId, columnWidths[columnId], e);
        }
    }, [onColumnResizeStart, columnWidths]);
    const handleColumnResizeEnd = useCallback((columnId, e) => {
        if (onColumnResizeEnd && columnWidths) {
            onColumnResizeEnd(columnId, columnWidths[columnId], e);
        }
    }, [onColumnResizeEnd, columnWidths]);
    const getTableWidth = useCallback((fallbackWidth) => {
        if (!isTableResizable) {
            return fallbackWidth || '100%';
        }
        return 'fit-content';
    }, [isTableResizable]);
    const contextValue = useMemo(() => ({
        columnWidths,
        getEffectiveColumnWidth,
        getStickyColumnStyle,
        getTableWidth,
        resizeColumn: handleColumnResize,
        startColumnResize: handleColumnResizeStart,
        endColumnResize: handleColumnResizeEnd,
    }), [
        columnWidths,
        getEffectiveColumnWidth,
        getStickyColumnStyle,
        getTableWidth,
        handleColumnResize,
        handleColumnResizeStart,
        handleColumnResizeEnd,
    ]);
    return (React.createElement(ColumnResizeContext.Provider, { value: contextValue }, children));
};
//# sourceMappingURL=ColumnResize.js.map