/*!
 * Custom elements for Nanopore-Digital Web applications
 */
import { h } from "../../utils/renderer";
import { headerPinClasses, mergeProperties, rowDataModel } from "./table.utils";
import { baseCellClasses } from "./table.cell";
import { CSSNAMESPACE } from "./table.constants";
const tableCellContent = (props, children, ctx) => {
    const cell = (h("div", { ...props.wrapperProps, class: {
            [`${CSSNAMESPACE}__cell-content`]: true,
            [`${CSSNAMESPACE}__cell-content--wrap`]: props.wrap,
        } }, children));
    return props.header ? (h("th", { scope: ctx, ...props.cellProps }, cell)) : (h("td", { ...props.cellProps }, cell));
};
export const TableRow = ({ rowRenderer, rowIndex, rowModel }, children, utils) => {
    // helper, generates <td> or <th>
    const TableCell = ({ header, wrap, cellProps, wrapperProps }, children) => {
        return tableCellContent({ header, wrap, cellProps, wrapperProps }, children, 'row');
    };
    let extraProps = {};
    if (!rowModel) {
        const model = rowDataModel(rowIndex);
        rowModel = model.rowModel;
    }
    if (rowRenderer?.rowProperties) {
        extraProps =
            rowRenderer.rowProperties({ rowModel, rowIndex }) || extraProps;
    }
    let rowPinned;
    if (rowRenderer?.pinned && typeof rowRenderer.pinned === 'function') {
        rowPinned = rowRenderer.pinned({ rowModel, rowIndex });
    }
    const props = mergeProperties({ class: headerPinClasses('tr', rowPinned, true) }, extraProps);
    const tpl = rowRenderer?.template;
    /**
     * Applies appropriate classes to td / th VNodes;
     * which can be supplied by user defined templates
     * @param children virtual / jsx node array
     * @returns virtual / jsx node array
     */
    const applyCellClasses = (children) => {
        return utils.map(children, (cNode, i) => {
            if (['td', 'th'].includes(cNode.vtag.toString())) {
                cNode.vattrs = mergeProperties({
                    class: baseCellClasses(i, true),
                }, cNode.vattrs);
            }
            return cNode;
        });
    };
    if (tpl) {
        let toRender = tpl(h, {
            renderedRow: (h("tr", { ...props, key: rowModel.__uuid }, children)),
            rowModel,
            rowIndex,
        }, TableCell);
        if (Array.isArray(toRender)) {
            toRender = utils.map(toRender, (node, i) => {
                if (node.vtag === 'tr') {
                    if (!node.vkey)
                        node.vkey = `${rowModel.__uuid}_${i}`;
                    node.vattrs = mergeProperties({ class: headerPinClasses('tr', rowPinned, true) }, node.vattrs);
                    if (node.vchildren) {
                        node.vchildren = applyCellClasses(node.vchildren);
                    }
                }
                return node;
            });
        }
        return toRender;
    }
    return (h("tr", { ...props, key: rowModel.__uuid }, applyCellClasses(children)));
};
export const TableHeadFootRow = ({ rowRenderer }, // onRowPinned, onColPinned
children, utils) => {
    let extraProps = {};
    if (rowRenderer.rowProperties) {
        extraProps = rowRenderer.rowProperties() || {};
    }
    const TableHeadFootCell = ({ header, wrap, cellProps, wrapperProps }, children) => {
        return tableCellContent({ header, wrap, cellProps, wrapperProps }, children, 'col');
    };
    const pinned = rowRenderer.pinned || null;
    const baseProps = { class: headerPinClasses('tr', pinned) };
    const props = extraProps ? mergeProperties(baseProps, extraProps) : baseProps;
    const tpl = rowRenderer?.template;
    if (tpl) {
        let toRender = tpl(h, {
            renderedRow: h("tr", { ...props }, children),
        }, TableHeadFootCell);
        if (Array.isArray(toRender)) {
            toRender = utils.map(toRender, (node) => {
                if (node.vtag === 'tr') {
                    node.vattrs = mergeProperties({ class: headerPinClasses('tr', pinned, true) }, node.vattrs);
                    if (node.vchildren) {
                        node.vchildren = utils.map(node.vchildren, (cNode) => {
                            if (['td', 'th'].includes(cNode.vtag.toString())) {
                                cNode.vattrs = mergeProperties({
                                    class: headerPinClasses(cNode.vtag.toString(), pinned, true),
                                }, cNode.vattrs);
                            }
                            return cNode;
                        });
                    }
                }
                return node;
            });
        }
        return toRender;
    }
    return h("tr", { ...props }, children);
};
