import { getMemoOptions, memo } from '../utils';
export function createColumn(table, columnDef, depth, parent) {
    var _a, _b, _c;
    const defaultColumn = table._getDefaultColumnDef();
    const resolvedColumnDef = {
        ...defaultColumn,
        ...columnDef,
    };
    const { accessorKey } = resolvedColumnDef;
    let idPart;
    if (!accessorKey) {
        idPart = undefined;
    }
    else {
        idPart =
            typeof String.prototype.replaceAll === 'function'
                ? accessorKey.replaceAll('.', '_')
                : accessorKey.replace(/\./g, '_');
    }
    const id = (_b = (_a = resolvedColumnDef.id) !== null && _a !== void 0 ? _a : idPart) !== null && _b !== void 0 ? _b : (typeof resolvedColumnDef.header === 'string' ? resolvedColumnDef.header : undefined);
    let accessorFn;
    if (resolvedColumnDef.accessorFn) {
        accessorFn = resolvedColumnDef.accessorFn;
    }
    else if (accessorKey) {
        // Support deep accessor keys
        if (accessorKey.includes('.')) {
            accessorFn = (originalRow) => {
                let result = originalRow;
                for (const key of accessorKey.split('.')) {
                    result = result === null || result === void 0 ? void 0 : result[key];
                    if (process.env.NODE_ENV !== 'production' && result === undefined) {
                        console.warn(`"${key}" in deeply nested key "${accessorKey}" returned undefined.`);
                    }
                }
                return result;
            };
        }
        else {
            accessorFn = (originalRow) => originalRow[resolvedColumnDef.accessorKey];
        }
    }
    if (!id) {
        if (process.env.NODE_ENV !== 'production') {
            throw new Error(resolvedColumnDef.accessorFn
                ? `Columns require an id when using an accessorFn`
                : `Columns require an id when using a non-string header`);
        }
        throw new Error();
    }
    const column = {
        id: `${String(id)}`,
        accessorFn,
        parent: parent,
        depth,
        columnDef: resolvedColumnDef,
        columns: [],
        getFlatColumns: memo(() => [true], () => {
            var _a;
            return [
                column,
                ...(_a = column.columns) === null || _a === void 0 ? void 0 : _a.flatMap((d) => d.getFlatColumns()),
            ];
        }, getMemoOptions(table.options, 'debugColumns', 'column.getFlatColumns')),
        getLeafColumns: memo(() => [table._getOrderColumnsFn()], (orderColumns) => {
            var _a;
            if ((_a = column.columns) === null || _a === void 0 ? void 0 : _a.length) {
                const leafColumns = column.columns.flatMap((col) => col.getLeafColumns());
                return orderColumns(leafColumns);
            }
            return [column];
        }, getMemoOptions(table.options, 'debugColumns', 'column.getLeafColumns')),
    };
    for (const feature of table._features) {
        (_c = feature.createColumn) === null || _c === void 0 ? void 0 : _c.call(feature, column, table);
    }
    // Yes, we have to convert table to unknown, because we know more than the compiler here.
    return column;
}
