import * as React from 'react';
import * as ReactDOMServer from 'react-dom/server';
import { constants, coord, func, util } from '../common';
import * as css from '../styles/global.cell';
const CLASS = css.CLASS;
const { CELL, GRID } = CLASS;
export const cellRenderer = (grid, factory) => {
    const CACHE = {};
    function toHtml(args) {
        const el = toElement(args);
        return ReactDOMServer.renderToString(el);
    }
    function toElement(args) {
        const { row, column, cell } = args;
        const child = factory.cell({ row, column, cell });
        const isHtml = typeof child === 'string' && child.startsWith('<');
        const props = cell ? cell.props || {} : {};
        const style = props.style || {};
        const view = (props.view && props.view.cell) || constants.DEFAULT.CELL.PROPS.view.cell;
        let className = CELL.BASE;
        const add = (isRequired, value) => (className = isRequired && value ? `${className} ${value}` : className);
        add(isHtml, CELL.MARKDOWN);
        add(row === 0, GRID.FIRST.ROW);
        add(column === 0, GRID.FIRST.COLUMN);
        add(style.bold, CELL.BOLD);
        add(style.italic, CELL.ITALIC);
        add(style.underline, CELL.UNDERLINE);
        add(func.isFormula(cell && cell.value), CELL.FORMULA);
        add(Boolean(view.className), view.className);
        add(Boolean(cell && cell.error), CELL.ERROR);
        if (isHtml) {
            return React.createElement("div", { className: className, dangerouslySetInnerHTML: { __html: child } });
        }
        else {
            return React.createElement("div", { className: className }, child);
        }
    }
    function toCellHash(args) {
        const { row, column, cell } = args;
        return cell ? cell.hash || util.gridCellHash(grid, coord.cell.toKey(column, row), cell) : '-';
    }
    function toMemoizedHtml(args) {
        const { row, column, cell } = args;
        const hash = toCellHash({ row, column, cell });
        const key = `${row}:${column}/${hash}`;
        if (CACHE[key]) {
            return CACHE[key];
        }
        const html = toHtml(args);
        CACHE[key] = html;
        return html;
    }
    const fn = (instance, td, row, column, prop, value, cellProps) => {
        if (!grid.isDisposed) {
            td.innerHTML = toMemoizedHtml({ td, row, column, cell: value });
        }
        return td;
    };
    return fn;
};
export function registerCellRenderer(Table, grid, factory) {
    const renderers = Table.renderers;
    const fn = renderers.registerRenderer;
    fn(constants.DEFAULT.CELL.RENDERER, cellRenderer(grid, factory));
}
