"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var tslib_1 = require("tslib");
var global_1 = require("@dojo/framework/shim/global");
var WidgetBase_1 = require("@dojo/framework/core/WidgetBase");
var vdom_1 = require("@dojo/framework/core/vdom");
var I18n_1 = require("@dojo/framework/core/mixins/I18n");
var Themed_1 = require("@dojo/framework/core/mixins/Themed");
var vdom_2 = require("@dojo/framework/core/vdom");
var PlaceholderRow_1 = require("./PlaceholderRow");
var Row_1 = require("./Row");
var fixedCss = require("./styles/body.m.css");
var css = require("../theme/default/grid-body.m.css");
var diffProperty_1 = require("@dojo/framework/core/decorators/diffProperty");
var diff_1 = require("@dojo/framework/core/diff");
var offscreen = function (dnode) {
    var r = vdom_2.default(function () {
        return vdom_1.w(/** @class */ (function (_super) {
            tslib_1.__extends(class_1, _super);
            function class_1() {
                return _super !== null && _super.apply(this, arguments) || this;
            }
            class_1.prototype.render = function () {
                return dnode;
            };
            return class_1;
        }(WidgetBase_1.default)), {});
    });
    var div = global_1.default.document.createElement('div');
    div.style.position = 'absolute';
    global_1.default.document.body.appendChild(div);
    r.mount({ domNode: div, sync: true });
    var dimensions = div.getBoundingClientRect();
    global_1.default.document.body.removeChild(div);
    return dimensions;
};
var Body = /** @class */ (function (_super) {
    tslib_1.__extends(Body, _super);
    function Body() {
        var _this = _super !== null && _super.apply(this, arguments) || this;
        _this._start = 0;
        _this._end = 100;
        _this._resetScroll = false;
        return _this;
    }
    Body.prototype._defaultPlaceholderRow = function (key) {
        var _a = this.properties, classes = _a.classes, theme = _a.theme;
        return vdom_1.w(PlaceholderRow_1.default, { key: key, theme: theme, classes: classes });
    };
    Body.prototype._updater = function (rowNumber, columnId, value) {
        var page = Math.max(Math.ceil(rowNumber / this.properties.pageSize), 1);
        var pageItemNumber = rowNumber - (page - 1) * this.properties.pageSize;
        this.properties.updater(page, pageItemNumber, columnId, value);
    };
    Body.prototype._onScroll = function (event) {
        var _a = this.properties, _b = _a.totalRows, totalRows = _b === void 0 ? 0 : _b, onScroll = _a.onScroll;
        var scrollTop = event.target.scrollTop;
        var scrollLeft = event.target.scrollLeft;
        var topRow = Math.round(scrollTop / this._rowHeight);
        var bottomRow = topRow + this._rowsInView;
        if (topRow <= this._start) {
            this._start = Math.max(0, topRow - this._renderPageSize);
            this._end = Math.min(totalRows, this._start + this._renderPageSize * 2);
        }
        if (bottomRow >= this._end) {
            this._start = Math.min(topRow, totalRows - this._renderPageSize);
            this._end = Math.min(totalRows, this._start + this._renderPageSize * 2);
        }
        onScroll && onScroll(scrollLeft);
        this.invalidate();
    };
    Body.prototype._onDiffTotalRows = function () {
        this._start = 0;
        this._end = 100;
        this._resetScroll = true;
    };
    Body.prototype._renderRows = function (start, end) {
        var _a = this.properties, i18nBundle = _a.i18nBundle, pageSize = _a.pageSize, fetcher = _a.fetcher, pages = _a.pages, columnConfig = _a.columnConfig, _b = _a.placeholderRowRenderer, placeholderRowRenderer = _b === void 0 ? this._defaultPlaceholderRow : _b, pageChange = _a.pageChange, totalRows = _a.totalRows, theme = _a.theme, classes = _a.classes, columnWidths = _a.columnWidths, onRowSelect = _a.onRowSelect, _c = _a.selectedRows, selectedRows = _c === void 0 ? [] : _c;
        var startPage = Math.max(Math.ceil(start / pageSize), 1);
        var endPage = Math.ceil(end / pageSize);
        var data = pages["page-" + startPage] || [];
        if (!data.length && (totalRows === undefined || totalRows > 0)) {
            fetcher(startPage, pageSize);
        }
        if (startPage !== endPage) {
            var endData = pages["page-" + endPage] || [];
            if (!endData.length) {
                fetcher(endPage, pageSize);
            }
            var midScreenPage = Math.max(Math.ceil((start + this._rowsInView / 2) / pageSize), 1);
            pageChange(midScreenPage);
            data = tslib_1.__spread(data, endData);
        }
        else {
            pageChange(startPage);
        }
        var rows = [];
        var _loop_1 = function (i) {
            var offset = i - (startPage * pageSize - pageSize);
            var item = data[offset];
            if (item) {
                rows.push(vdom_1.w(Row_1.default, {
                    id: i,
                    key: i,
                    i18nBundle: i18nBundle,
                    theme: theme,
                    classes: classes,
                    item: item,
                    columnConfig: columnConfig,
                    updater: this_1._updater,
                    columnWidths: columnWidths,
                    onRowSelect: onRowSelect
                        ? function (type) {
                            onRowSelect(i, type);
                        }
                        : undefined,
                    selected: selectedRows.indexOf(i) !== -1
                }));
            }
            else {
                if (totalRows === undefined || (i > -1 && i < totalRows)) {
                    rows.push(placeholderRowRenderer(i));
                }
            }
        };
        var this_1 = this;
        for (var i = start; i < end; i++) {
            _loop_1(i);
        }
        return rows;
    };
    Body.prototype.render = function () {
        var _a = this.properties, _b = _a.placeholderRowRenderer, placeholderRowRenderer = _b === void 0 ? this._defaultPlaceholderRow : _b, _c = _a.totalRows, totalRows = _c === void 0 ? 0 : _c, pageSize = _a.pageSize, height = _a.height, width = _a.width, columnWidths = _a.columnWidths;
        var rowWidth = columnWidths &&
            Object.keys(columnWidths).reduce(function (rowWidth, key) {
                return rowWidth + columnWidths[key];
            }, 0);
        if (!this._rowHeight) {
            var firstRow = placeholderRowRenderer(0);
            var dimensions = offscreen(firstRow);
            this._rowHeight = dimensions.height;
            this._rowsInView = Math.ceil(height / this._rowHeight);
            this._renderPageSize = this._rowsInView * 2;
        }
        var rows = this._renderRows(this._start, this._end);
        var topPaddingHeight = this._rowHeight * this._start;
        var bottomPaddingHeight = 0;
        if (totalRows >= pageSize) {
            bottomPaddingHeight =
                totalRows * this._rowHeight -
                    topPaddingHeight -
                    (this._end - this._start) * this._rowHeight;
        }
        var containerProperties = {
            key: 'root',
            classes: [this.theme(css.root), fixedCss.rootFixed],
            role: 'rowgroup',
            onscroll: this._onScroll,
            styles: width
                ? { height: height + "px", width: width + "px" }
                : { height: height + "px" }
        };
        if (this._resetScroll) {
            this._resetScroll = false;
            containerProperties = tslib_1.__assign({}, containerProperties, { scrollTop: 0 });
        }
        return vdom_1.v('div', containerProperties, [
            vdom_1.v('div', { styles: rowWidth ? { width: rowWidth + "px" } : {} }, tslib_1.__spread([
                vdom_1.v('div', { key: 'top', styles: { height: topPaddingHeight + "px" } })
            ], rows, [
                vdom_1.v('div', {
                    key: 'bottom',
                    styles: { height: bottomPaddingHeight + "px" }
                })
            ]))
        ]);
    };
    tslib_1.__decorate([
        diffProperty_1.diffProperty('totalRows', diff_1.auto),
        tslib_1.__metadata("design:type", Function),
        tslib_1.__metadata("design:paramtypes", []),
        tslib_1.__metadata("design:returntype", void 0)
    ], Body.prototype, "_onDiffTotalRows", null);
    Body = tslib_1.__decorate([
        Themed_1.theme(css),
        diffProperty_1.diffProperty('pages', diff_1.reference)
    ], Body);
    return Body;
}(I18n_1.default(Themed_1.default(WidgetBase_1.default))));
exports.default = Body;

/*# sourceMappingURL=Body.js.map*/