import type { RefObject } from 'react';
import { useCallback } from 'react';
import { TableExtensions } from '../tableExtensions';
import { createColumnDefinitions, createColumnInstances, getVisibleColumns } from './columns';
import { useLayoutInfo } from './layout';
import { useRowFlags } from './rowFlags';
import { createRowInstances } from './rows';
import { useSortedTable } from './sort';
import type { TableApi, TableProps } from '../types';

export function useTableApi<Data>(
    tableProps: TableProps<Data>,
    wrapperRef: RefObject<HTMLDivElement>
): TableApi<Data> {
    const initialProps = {
        ...tableProps,
        name: tableProps.name ?? 'table',
        data: tableProps.data ?? [],
        columnDefs: createColumnDefinitions(tableProps),
    };

    const props = TableExtensions.onPropsInit(initialProps);

    const toggleTableClassName = useCallback(
        (name: string, value: boolean) => {
            if (value) wrapperRef.current?.classList.add(name);
            else wrapperRef.current?.classList.remove(name);
        },
        [wrapperRef]
    );

    const { rowFlags, setRowFlags } = useRowFlags();

    const { layoutInfo, refresh } = useLayoutInfo(wrapperRef);

    const { sortedRows, getSortConfig, setSortedColumn } = useSortedTable(props);

    const rows = TableExtensions.onRowsCreated(
        createRowInstances({ ...props, data: sortedRows }, rowFlags),
        props
    );

    const columns = createColumnInstances({
        columnDefs: props.columnDefs,
        getSortConfig,
    });

    const api: TableApi<Data> = {
        columns,
        visibleColumns: [],
        rows,
        layoutInfo,
        setSortedColumn,
        setRowFlags,
        props,
        initialProps,
        refresh,
        toggleTableClassName,
        wrapperRef,
    };

    columns.forEach((column) => {
        const instance = column;
        const {
            definition: { getDisplayMode },
        } = instance;

        if (getDisplayMode) instance.display = getDisplayMode(api);
    });

    api.visibleColumns = getVisibleColumns(columns, props.hideColumnSeparators);

    return api;
}
