"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var tslib_1 = require("tslib");
require("./utils");
var WidgetBase_1 = require("@dojo/framework/core/WidgetBase");
var diffProperty_1 = require("@dojo/framework/core/decorators/diffProperty");
var diff_1 = require("@dojo/framework/core/diff");
var Dimensions_1 = require("@dojo/framework/core/meta/Dimensions");
var Resize_1 = require("@dojo/framework/core/meta/Resize");
var I18n_1 = require("@dojo/framework/core/mixins/I18n");
var Themed_1 = require("@dojo/framework/core/mixins/Themed");
var vdom_1 = require("@dojo/framework/core/vdom");
var Store_1 = require("@dojo/framework/stores/Store");
var css = require("../theme/default/grid.m.css");
var Body_1 = require("./Body");
var Footer_1 = require("./Footer");
var Header_1 = require("./Header");
var PaginatedBody_1 = require("./PaginatedBody");
var PaginatedFooter_1 = require("./PaginatedFooter");
var processes_1 = require("./processes");
var fixedCss = require("./styles/grid.m.css");
var defaultGridMeta = {
    page: 1,
    total: undefined,
    sort: undefined,
    filter: undefined,
    isSorting: false,
    editedRow: undefined,
    selection: []
};
var MIN_COLUMN_WIDTH = 100;
var Grid = /** @class */ (function (_super) {
    tslib_1.__extends(Grid, _super);
    function Grid() {
        var _this = _super.call(this) || this;
        _this._store = new Store_1.Store();
        _this._scrollLeft = 0;
        _this._pageSize = 100;
        _this._gridWidth = 0;
        _this._handle = _this._store.onChange(_this._store.path('_grid'), _this.invalidate.bind(_this));
        return _this;
    }
    Grid.prototype.onStoreProperty = function (previous, current) {
        var _this = this;
        var _a = current.storeId, storeId = _a === void 0 ? '_grid' : _a;
        this._handle.remove();
        this._store = current.store;
        this._handle = this._store.onChange(this._store.path(storeId), function () {
            _this.invalidate();
        });
    };
    Grid.prototype._getProperties = function () {
        var _a = this.properties.storeId, storeId = _a === void 0 ? '_grid' : _a;
        return tslib_1.__assign({}, this.properties, { storeId: storeId });
    };
    Grid.prototype._getBodyDimensions = function () {
        var height = this.properties.height;
        var headerWrapper = this.meta(Dimensions_1.default).get('header-wrapper');
        var _a = this.meta(Dimensions_1.default).get('header').size, headerHeight = _a.height, bodyWidth = _a.width;
        var footerHeight = this.meta(Dimensions_1.default).get('footer').size.height;
        return {
            headerWidth: headerWrapper.size.width,
            bodyHeight: footerHeight && footerHeight ? height - headerHeight - footerHeight : 0,
            bodyWidth: bodyWidth
        };
    };
    Grid.prototype._onColumnResize = function (index, value) {
        var _a;
        var columnConfig = this.properties.columnConfig;
        if (!this._columnWidths) {
            return;
        }
        var currentColumnWidth = this._columnWidths[columnConfig[index].id];
        if (currentColumnWidth <= MIN_COLUMN_WIDTH && value < 0) {
            return;
        }
        if (currentColumnWidth + value <= MIN_COLUMN_WIDTH) {
            value = value - (currentColumnWidth + value - MIN_COLUMN_WIDTH);
        }
        this._columnWidths = tslib_1.__assign({}, this._columnWidths, (_a = {}, _a[columnConfig[index].id] = currentColumnWidth + value, _a));
        this.invalidate();
    };
    Grid.prototype._fetcher = function (page, pageSize) {
        var _a = this._getProperties(), storeId = _a.storeId, fetcher = _a.fetcher;
        processes_1.fetcherProcess(this._store)({ id: storeId, fetcher: fetcher, page: page, pageSize: pageSize });
    };
    Grid.prototype._sorter = function (columnId, direction) {
        var _a = this._getProperties(), storeId = _a.storeId, fetcher = _a.fetcher, onRowSelect = _a.onRowSelect;
        if (onRowSelect) {
            var selectedIndexes = this._store.get(this._store.path(storeId, 'meta', 'selection')) || [];
            selectedIndexes.length && onRowSelect([]);
        }
        processes_1.sortProcess(this._store)({ id: storeId, fetcher: fetcher, columnId: columnId, direction: direction });
    };
    Grid.prototype._filterer = function (columnId, value) {
        var _a = this._getProperties(), storeId = _a.storeId, fetcher = _a.fetcher, onRowSelect = _a.onRowSelect;
        if (onRowSelect) {
            var selectedIndexes = this._store.get(this._store.path(storeId, 'meta', 'selection')) || [];
            selectedIndexes.length && onRowSelect([]);
        }
        processes_1.filterProcess(this._store)({ id: storeId, fetcher: fetcher, filterOptions: { columnId: columnId, value: value } });
    };
    Grid.prototype._updater = function (page, rowNumber, columnId, value) {
        var _a = this._getProperties(), storeId = _a.storeId, updater = _a.updater;
        processes_1.updaterProcess(this._store)({ id: storeId, page: page, columnId: columnId, rowNumber: rowNumber, value: value, updater: updater });
    };
    Grid.prototype._pageChange = function (page) {
        var _a = this._getProperties(), pagination = _a.pagination, storeId = _a.storeId;
        if (pagination) {
            processes_1.clearSelectionProcess(this._store)({ id: storeId });
        }
        processes_1.pageChangeProcess(this._store)({ id: storeId, page: page });
    };
    Grid.prototype._selection = function (index, type) {
        var _a = this._getProperties(), storeId = _a.storeId, onRowSelect = _a.onRowSelect;
        processes_1.selectionProcess(this._store)({ id: storeId, index: index, type: type });
        var selectedIndexes = this._store.get(this._store.path(storeId, 'meta', 'selection')) || [];
        var items = [];
        var data = this._store.get(this._store.path(storeId, 'data', 'pages'));
        var pageNumber = this._store.get(this._store.path(storeId, 'meta', 'page'));
        for (var i = 0; i < selectedIndexes.length; i++) {
            var selectedIndex = selectedIndexes[i];
            var offset = Math.floor(selectedIndex / this._pageSize) + 1;
            var itemIndex = selectedIndex - (offset - 1) * this._pageSize;
            if (data["page-" + pageNumber]) {
                items.push(data["page-" + pageNumber][itemIndex]);
            }
        }
        onRowSelect && onRowSelect(items);
    };
    Grid.prototype._onScroll = function (value) {
        this._scrollLeft = value;
        this.invalidate();
    };
    Grid.prototype.render = function () {
        var _this = this;
        var _a = this._getProperties(), i18nBundle = _a.i18nBundle, columnConfig = _a.columnConfig, storeId = _a.storeId, theme = _a.theme, classes = _a.classes, _b = _a.pagination, pagination = _b === void 0 ? false : _b, _c = _a.customRenderers, customRenderers = _c === void 0 ? {} : _c, onRowSelect = _a.onRowSelect;
        var sortRenderer = customRenderers.sortRenderer, filterRenderer = customRenderers.filterRenderer;
        if (!columnConfig || !this.properties.fetcher) {
            return null;
        }
        var meta = this._store.get(this._store.path(storeId, 'meta')) || defaultGridMeta;
        var pages = this._store.get(this._store.path(storeId, 'data', 'pages')) || {};
        var hasFilters = columnConfig.some(function (config) { return !!config.filterable; });
        var hasResizableColumns = columnConfig.some(function (config) { return !!config.resizable; });
        var _d = this._getBodyDimensions(), bodyHeight = _d.bodyHeight, bodyWidth = _d.bodyWidth, headerWidth = _d.headerWidth;
        this.meta(Resize_1.default).get('root');
        if (bodyWidth && headerWidth && hasResizableColumns && !this._columnWidths) {
            var width_1 = headerWidth / columnConfig.length;
            this._columnWidths = columnConfig.reduce(function (sizes, _a) {
                var id = _a.id;
                sizes[id] = Math.max(MIN_COLUMN_WIDTH, width_1);
                return sizes;
            }, {});
            this._gridWidth = Math.max(bodyWidth, MIN_COLUMN_WIDTH * columnConfig.length);
        }
        return vdom_1.v('div', {
            key: 'root',
            classes: [this.variant(), this.theme(css.root), fixedCss.rootFixed],
            role: 'table',
            'aria-rowcount': meta.total ? "" + meta.total : undefined
        }, [
            vdom_1.v('div', {
                key: 'header',
                scrollLeft: this._scrollLeft,
                styles: hasResizableColumns && this._gridWidth
                    ? {
                        width: this._gridWidth + "px"
                    }
                    : {},
                classes: [
                    this.theme(css.header),
                    fixedCss.headerFixed,
                    hasFilters ? this.theme(css.filterGroup) : null
                ],
                row: 'rowgroup'
            }, [
                vdom_1.v('div', { key: 'header-wrapper' }, [
                    vdom_1.w(Header_1.default, {
                        key: 'header-row',
                        i18nBundle: i18nBundle,
                        theme: theme,
                        columnWidths: this._columnWidths,
                        classes: classes,
                        columnConfig: columnConfig,
                        sorter: this._sorter,
                        sort: meta.sort,
                        filter: meta.filter,
                        filterer: this._filterer,
                        sortRenderer: sortRenderer,
                        filterRenderer: filterRenderer,
                        onColumnResize: this._onColumnResize
                    })
                ])
            ]),
            bodyHeight
                ? pagination
                    ? vdom_1.w(PaginatedBody_1.default, {
                        key: 'paginated-body',
                        i18nBundle: i18nBundle,
                        theme: theme,
                        classes: classes,
                        pages: pages,
                        columnWidths: this._columnWidths,
                        pageNumber: meta.page,
                        pageSize: this._pageSize,
                        onScroll: this._onScroll,
                        columnConfig: columnConfig,
                        fetcher: this._fetcher,
                        updater: this._updater,
                        height: bodyHeight,
                        width: hasResizableColumns ? this._gridWidth : undefined,
                        onRowSelect: onRowSelect ? this._selection : undefined,
                        selectedRows: meta.selection
                    })
                    : vdom_1.w(Body_1.default, {
                        key: 'body',
                        i18nBundle: i18nBundle,
                        theme: theme,
                        classes: classes,
                        pages: pages,
                        columnWidths: this._columnWidths,
                        totalRows: meta.total,
                        pageSize: this._pageSize,
                        columnConfig: columnConfig,
                        fetcher: this._fetcher,
                        pageChange: this._pageChange,
                        updater: this._updater,
                        onScroll: this._onScroll,
                        height: bodyHeight,
                        width: hasResizableColumns ? this._gridWidth : undefined,
                        onRowSelect: onRowSelect ? this._selection : undefined,
                        selectedRows: meta.selection
                    })
                : null,
            vdom_1.v('div', { key: 'footer' }, [
                pagination
                    ? vdom_1.w(PaginatedFooter_1.default, {
                        i18nBundle: i18nBundle,
                        theme: theme,
                        classes: classes,
                        total: meta.total,
                        page: meta.page,
                        pageSize: this._pageSize,
                        onPageChange: function (page) {
                            _this._pageChange(page);
                        }
                    })
                    : vdom_1.w(Footer_1.default, {
                        key: 'footer-row',
                        i18nBundle: i18nBundle,
                        theme: theme,
                        classes: classes,
                        total: meta.total,
                        page: meta.page,
                        pageSize: this._pageSize
                    })
            ])
        ]);
    };
    tslib_1.__decorate([
        diffProperty_1.default('store', diff_1.reference),
        tslib_1.__metadata("design:type", Function),
        tslib_1.__metadata("design:paramtypes", [Object, Object]),
        tslib_1.__metadata("design:returntype", void 0)
    ], Grid.prototype, "onStoreProperty", null);
    Grid = tslib_1.__decorate([
        Themed_1.theme(css),
        tslib_1.__metadata("design:paramtypes", [])
    ], Grid);
    return Grid;
}(I18n_1.default(Themed_1.default(WidgetBase_1.default))));
exports.default = Grid;

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