/*!
 * Custom elements for Nanopore-Digital Web applications
 */
import { Fragment, getRenderingRef, } from "@stencil/core";
import { h } from "../../utils/renderer";
import { CSSNAMESPACE } from "./table.constants";
import { classListToStr, colDataModel, fetchStores, mergeCellProperties, } from "./table.utils";
// TABLE CELL
// (tbody > tr > td, tbody > tr > th)
/**
 * Renders a cell using a custom renderer if set.
 * @param rowIndex - the current row index being rendered
 * @param colIndex - the current column index being rendered
 * @returns - a JSX node
 */
function cellRender(rowIndex, colIndex) {
    const store = fetchStores();
    const columns = store.config.state.columns;
    const tpl = columns[colIndex]?.cellTemplate;
    const model = colDataModel(rowIndex, colIndex);
    const tableInstance = getRenderingRef();
    if (!!model.cellModel && columns[colIndex].type === 'date') {
        const d = new Date(model.cellModel);
        if (d instanceof Date && !isNaN(d)) {
            model.cellModel = !tpl
                ? `${new Date(model.cellModel).toLocaleDateString()} ${new Date(model.cellModel).toLocaleTimeString()}`
                : d;
        }
    }
    // Wrap the h pragma, then we can know if we're using Stencil's
    // jsx renderer or a different one
    let hCalled = false;
    const hWrap = (...args) => {
        hCalled = true;
        // @ts-expect-error - h mismatch
        return h(...args);
    };
    let tplResult = tpl ? tpl(hWrap, model) : undefined;
    if (tplResult &&
        tableInstance.customRenderer &&
        tplResult['$attrs$'] === undefined &&
        !(tplResult instanceof Element) &&
        typeof tplResult !== 'string' &&
        !hCalled) {
        // template result is jsx *not* from Stencil.
        // Render it now and output it later.
        const templateEle = document.createElement('template');
        const result = tableInstance.customRenderer(tplResult, templateEle.content);
        // custom rendering can render to the templateEle OR return a promise<string>
        tplResult = result && result['then'] ? result : templateEle;
    }
    return tplResult ? tplResult : model.cellModel !== undefined && model.cellModel !== null ? (h(Fragment, null, model.cellModel?.toString())) : ('');
}
export const baseCellClasses = (colIndex, toString = false) => {
    const store = fetchStores();
    const column = store.config.state.columns[colIndex];
    const classes = {
        [`${CSSNAMESPACE}__td`]: true,
        [`${CSSNAMESPACE}__ordered`]: !!column.order,
        [`${CSSNAMESPACE}__pin`]: !!column.pinned,
        [`${CSSNAMESPACE}__pin--start`]: column.pinned === 'start',
        [`${CSSNAMESPACE}__pin--end`]: column.pinned === 'end',
    };
    if (toString)
        return classListToStr(classes);
    return classes;
};
export const TableCell = ({ rowIndex, colIndex, nestedContent, }) => {
    const Content = () => nestedContent
        ? nestedContent()
        : cellRender(rowIndex, colIndex) || (h("span", { class: "placeholder" }, "\u00A0"));
    let CellType = 'td';
    const store = fetchStores();
    const column = store.config.state.columns[colIndex];
    if (column.hidden) {
        return h(Fragment, null);
    }
    let props = mergeCellProperties(rowIndex, colIndex, {
        class: baseCellClasses(colIndex),
    });
    if (column.rowHeader) {
        props =
            Number(props.rowSpan) > 1
                ? { ...props, scope: 'rowgroup' }
                : { ...props, scope: 'row' };
        CellType = 'th';
    }
    const ContentWrap = (props) => {
        const content = Content();
        return (h("div", { ref: (d) => {
                if (!d)
                    return;
                if (content instanceof Element) {
                    // custom rendered an element
                    d.replaceChildren();
                    d.append(content['content'] || content);
                }
                else if (content['then']) {
                    // custom rendered a promise. Most likely within SSR.
                    content.then((res) => (d.innerHTML = res));
                }
            }, ...props, class: {
                [`${CSSNAMESPACE}__cell-content`]: true,
                [`${CSSNAMESPACE}__cell-content--wrap`]: !!column.wrap,
            }, innerHTML: typeof content === 'string' && content.includes('<')
                ? content
                : undefined }, (typeof content !== 'string' || !content.includes('<')) &&
            !content['then'] &&
            !(content instanceof Element) &&
            content));
    };
    return (h(CellType, { ...props }, column.autoTooltip && !column.wrap ? (h("nano-resize-observe", { notifyContentFit: "x", onNanoResizeContentFitChange: (e) => (e.target.firstElementChild.disabled =
            e.detail.x) }, h("nano-tooltip", { disabled: true, placement: "top", onNanoShow: (e) => (e.target.closest(CellType).style.zIndex = '100'), onNanoHide: (e) => (e.target.closest(CellType).style.zIndex = '') }, h(ContentWrap, null), h("span", { slot: "content" }, h(Content, null))))) : (h(ContentWrap, null))));
};
