import * as tslib_1 from "tslib";
import { round } from '../internal';
import { isNumberColumn, isMultiLevelColumn } from '../model';
import { medianIndex } from '../model/internalNumber';
import { COLUMN_PADDING } from '../styles';
import { AAggregatedGroupRenderer } from './AAggregatedGroupRenderer';
import { ERenderMode } from './interfaces';
import { renderMissingCanvas, renderMissingDOM } from './missing';
import { matchColumns, multiLevelGridCSSClass } from './utils';
import { cssClass } from '../styles';
import { abortAbleAll } from 'lineupengine';
/** @internal */
export function createData(parent, context, stacked, mode, imposer) {
    var padding = COLUMN_PADDING;
    var offset = 0;
    var cols = parent.children.map(function (column) {
        var shift = offset;
        var width = column.getWidth();
        offset += width;
        offset += (!stacked ? padding : 0);
        var renderer = mode === ERenderMode.CELL ? context.renderer(column, imposer) : null;
        var groupRenderer = mode === ERenderMode.GROUP ? context.groupRenderer(column, imposer) : null;
        var summaryRenderer = mode === ERenderMode.GROUP ? context.summaryRenderer(column, false, imposer) : null;
        var template = '';
        var rendererId = '';
        switch (mode) {
            case ERenderMode.CELL:
                template = renderer.template;
                rendererId = column.getRenderer();
                break;
            case ERenderMode.GROUP:
                template = groupRenderer.template;
                rendererId = column.getGroupRenderer();
                break;
            case ERenderMode.SUMMARY:
                template = summaryRenderer.template;
                rendererId = column.getSummaryRenderer();
                break;
        }
        // inject data attributes
        template = template.replace(/^<([^ >]+)([ >])/, "<$1 data-column-id=\"" + column.id + "\" data-renderer=\"" + rendererId + "\"$2");
        // inject classes
        if (/^<([^>]+) class="([ >]*)/.test(template)) {
            // has class attribute
            template = template.replace(/^<([^>]+) class="([ >]*)/, "<$1 class=\"" + cssClass("renderer-" + rendererId) + " $2");
        }
        else {
            // inject as the others
            template = template.replace(/^<([^ >]+)([ >])/, "<$1 class=\"" + cssClass("renderer-" + rendererId) + "\"$2");
        }
        return {
            column: column,
            shift: shift,
            width: width,
            template: template,
            rendererId: rendererId,
            renderer: renderer,
            groupRenderer: groupRenderer,
            summaryRenderer: summaryRenderer
        };
    });
    return { cols: cols, stacked: stacked, padding: padding };
}
/** @internal */
var MultiLevelCellRenderer = /** @class */ (function (_super) {
    tslib_1.__extends(MultiLevelCellRenderer, _super);
    function MultiLevelCellRenderer(stacked) {
        if (stacked === void 0) { stacked = true; }
        var _this = _super.call(this) || this;
        _this.stacked = stacked;
        _this.title = _this.stacked ? 'Stacked Bar' : 'Nested';
        return _this;
    }
    MultiLevelCellRenderer.prototype.canRender = function (col, mode) {
        return isMultiLevelColumn(col) && mode !== ERenderMode.SUMMARY;
    };
    MultiLevelCellRenderer.prototype.create = function (col, context, imposer) {
        var _this = this;
        var _a = createData(col, context, this.stacked, ERenderMode.CELL, imposer), cols = _a.cols, stacked = _a.stacked;
        var width = context.colWidth(col);
        return {
            template: "<div class='" + multiLevelGridCSSClass(context.idPrefix, col) + " " + (!stacked ? cssClass('grid-space') : '') + "'>" + cols.map(function (d) { return d.template; }).join('') + "</div>",
            update: function (n, d, i, group) {
                if (renderMissingDOM(n, col, d)) {
                    return null;
                }
                matchColumns(n, cols, context);
                var toWait = [];
                var children = Array.from(n.children);
                var total = col.getWidth();
                var missingWeight = 0;
                cols.forEach(function (col, ci) {
                    var weight = col.column.getWidth() / total;
                    var cnode = children[ci];
                    cnode.classList.add(cssClass(_this.stacked ? 'stack-sub' : 'nested-sub'), cssClass('detail'));
                    cnode.dataset.group = 'd';
                    cnode.style.transform = stacked ? "translate(-" + round((missingWeight / weight) * 100, 4) + "%,0)" : null;
                    cnode.style.gridColumnStart = (ci + 1).toString();
                    var r = col.renderer.update(cnode, d, i, group);
                    if (stacked) {
                        missingWeight += (1 - col.column.getNumber(d)) * weight;
                    }
                    if (r) {
                        toWait.push(r);
                    }
                });
                if (toWait.length > 0) {
                    return abortAbleAll(toWait);
                }
                return null;
            },
            render: function (ctx, d, i, group) {
                if (renderMissingCanvas(ctx, col, d, width)) {
                    return null;
                }
                var toWait = [];
                var stackShift = 0;
                for (var _i = 0, cols_1 = cols; _i < cols_1.length; _i++) {
                    var col_1 = cols_1[_i];
                    var cr = col_1.renderer;
                    if (cr.render) {
                        var shift = col_1.shift - stackShift;
                        ctx.translate(shift, 0);
                        var r = cr.render(ctx, d, i, group);
                        if (typeof r !== 'boolean' && r) {
                            toWait.push({ shift: shift, r: r });
                        }
                        ctx.translate(-shift, 0);
                    }
                    if (stacked) {
                        stackShift += col_1.width * (1 - col_1.column.getNumber(d));
                    }
                }
                if (toWait.length === 0) {
                    return null;
                }
                return abortAbleAll(toWait.map(function (d) { return d.r; })).then(function (callbacks) {
                    return function (ctx) {
                        if (typeof callbacks === 'symbol') {
                            return;
                        }
                        for (var i_1 = 0; i_1 < callbacks.length; ++i_1) {
                            var callback = callbacks[i_1];
                            if (typeof callback !== 'function') {
                                continue;
                            }
                            var shift = toWait[i_1].shift;
                            ctx.translate(shift, 0);
                            callback(ctx);
                            ctx.translate(-shift, 0);
                        }
                    };
                });
            }
        };
    };
    MultiLevelCellRenderer.prototype.createGroup = function (col, context, imposer) {
        var _this = this;
        if (this.stacked && isNumberColumn(col)) {
            return _super.prototype.createGroup.call(this, col, context, imposer);
        }
        var cols = createData(col, context, false, ERenderMode.GROUP, imposer).cols;
        return {
            template: "<div class='" + multiLevelGridCSSClass(context.idPrefix, col) + " " + cssClass('grid-space') + "'>" + cols.map(function (d) { return d.template; }).join('') + "</div>",
            update: function (n, group) {
                matchColumns(n, cols, context);
                var toWait = [];
                var children = Array.from(n.children);
                cols.forEach(function (col, ci) {
                    var cnode = children[ci];
                    cnode.classList.add(cssClass(_this.stacked ? 'stack-sub' : 'nested-sub'), cssClass('group'));
                    cnode.dataset.group = 'g';
                    cnode.style.gridColumnStart = (ci + 1).toString();
                    var r = col.groupRenderer.update(cnode, group);
                    if (r) {
                        toWait.push(r);
                    }
                });
                if (toWait.length > 0) {
                    return abortAbleAll(toWait);
                }
                return null;
            }
        };
    };
    MultiLevelCellRenderer.prototype.aggregatedIndex = function (rows, col) {
        console.assert(isNumberColumn(col));
        return medianIndex(rows, col);
    };
    return MultiLevelCellRenderer;
}(AAggregatedGroupRenderer));
export default MultiLevelCellRenderer;
//# sourceMappingURL=MultiLevelCellRenderer.js.map