var __extends = (this && this.__extends) || (function () {
    var extendStatics = function (d, b) {
        extendStatics = Object.setPrototypeOf ||
            ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
            function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
        return extendStatics(d, b);
    };
    return function (d, b) {
        extendStatics(d, b);
        function __() { this.constructor = d; }
        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
    };
})();
var __assign = (this && this.__assign) || function () {
    __assign = Object.assign || function(t) {
        for (var s, i = 1, n = arguments.length; i < n; i++) {
            s = arguments[i];
            for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
                t[p] = s[p];
        }
        return t;
    };
    return __assign.apply(this, arguments);
};
var __rest = (this && this.__rest) || function (s, e) {
    var t = {};
    for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
        t[p] = s[p];
    if (s != null && typeof Object.getOwnPropertySymbols === "function")
        for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) if (e.indexOf(p[i]) < 0)
            t[p[i]] = s[p[i]];
    return t;
};
import { Store } from './Store';
import _ from 'lodash';
var ColumnsStore = /** @class */ (function (_super) {
    __extends(ColumnsStore, _super);
    function ColumnsStore(_a) {
        var items = _a.items, _b = _a.storeName, storeName = _b === void 0 ? 'ColumnsStore' : _b, _c = _a.visibleLimit, visibleLimit = _c === void 0 ? 0 : _c, params = __rest(_a, ["items", "storeName", "visibleLimit"]);
        var _this = _super.call(this, {
            stateName: params.stateName,
            fields: {
                id: {
                    type: String,
                    primaryKey: true
                },
                // custom test automation id, default is id property
                testAutomationId: {
                    type: String,
                    getter: function (item) {
                        return item.testAutomationId || item.id;
                    }
                },
                // zero based index of column. Columns ordered on grid according to this position
                position: Number,
                // label of column for rendering on grid header
                headerLabel: String,
                // description for grid columns editor
                description: String,
                // required columns can't be hidden on grid columns editor
                isRequired: Boolean,
                // user customization of column visibility
                isVisible: Boolean,
                // business logic checker to be called on particular column
                isAvailable: {
                    type: 'custom',
                    fieldFilterHandler: function (fieldValue, filter) {
                        return filter(fieldValue());
                    }
                },
                // customizable columns can be edited by user
                isCustomizable: Boolean,
                // additional filter to be able to getting columns for short view only
                // (when grid represented with short/full view)
                isForShortView: Boolean
            }
        }) || this;
        _this.defaults = items;
        _this.visibleLimit = visibleLimit;
        _this.register(storeName);
        return _this;
    }
    ColumnsStore.prototype.setVisibleColumns = function (listIds) {
        var items = this.getRawData().map(function (item) {
            return __assign({}, item, { isVisible: item.isCustomizable ? _.includes(listIds, item.id) : true });
        });
        this.setItems(items, false);
    };
    ColumnsStore.prototype.getColumnOffset = function (id) {
        var columns = this.getRawData();
        var currentPosition = _.find(columns, { id: id }).position;
        var columnsBefore = _.filter(columns, function (column) {
            var isCustomizable = column.isCustomizable, position = column.position;
            return position < currentPosition && !isCustomizable;
        });
        return columnsBefore.length;
    };
    /**
     * Setup new visual position for item
     * @param {Object} record
     * @param {Number} newPosition zero based index
     */
    ColumnsStore.prototype.setVisualPosition = function (record, newPosition) {
        if (record.position === newPosition) {
            return;
        }
        // get items ordered by position
        var items = this.getSortedByPosition(this.getRawData());
        // remove item
        _.remove(items, function (item) {
            return item.position === record.position;
        });
        var head = _.take(items, newPosition);
        var tail = _.takeRight(items, items.length - newPosition);
        var reorderedItems = head.concat([record], tail);
        // reset position
        reorderedItems = this.setupItemsPosition(reorderedItems);
        this.setItems(reorderedItems, true);
    };
    ColumnsStore.prototype.setupItemsPosition = function (items) {
        for (var i = 0; i < items.length; i++) {
            items[i].position = i;
        }
        return items;
    };
    ColumnsStore.prototype.getSortedByPosition = function (items) {
        return items.sort(function (a, b) { return a.position - b.position; });
    };
    ColumnsStore.prototype.isColumnCustomizable = function (id) {
        var columnSpec = _.find(this.getRawData(), { id: id });
        return columnSpec && columnSpec.isCustomizable;
    };
    ColumnsStore.prototype.getFromDefaults = function () {
        var defaults = {
            isVisible: true,
            isAvailable: _.stubTrue,
            isCustomizable: true,
            isForShortView: false,
            isRequired: false
        };
        var normalizeColumnSpec = function (columnSpec, index) {
            return __assign({}, defaults, columnSpec, { position: index });
        };
        return this.defaults.map(normalizeColumnSpec);
    };
    ColumnsStore.prototype.mergeItemsWithDefaults = function (items, defaults) {
        var columns = [];
        var extraColumns = [];
        if (items && items.length) {
            defaults.forEach(function (defaultSpec) {
                var item = _.find(items, { id: defaultSpec.id });
                if (item && defaultSpec.isAvailable()) {
                    columns.push(__assign({}, defaultSpec, item));
                }
                else {
                    extraColumns.push(defaultSpec);
                }
            });
            columns = this.getSortedByPosition(columns);
        }
        else {
            extraColumns = defaults;
        }
        if (extraColumns.length) {
            if (this.visibleLimit > 0) {
                var visibleLimit = this.visibleLimit - columns.filter(this.isCustomizableVisibleColumn).length;
                extraColumns = this.adjustExtraColumnsVisibility(extraColumns, visibleLimit);
            }
            columns = this.addExtraColumns(columns, extraColumns);
        }
        return columns;
    };
    ColumnsStore.prototype.adjustExtraColumnsVisibility = function (columns, visibleLimit) {
        var visibleCount = columns.filter(this.canBeHidden).length;
        if (visibleCount <= visibleLimit) {
            return columns;
        }
        for (var index = columns.length - 1; index > -1; index--) {
            var column = columns[index];
            if (this.canBeHidden(column)) {
                column.isVisible = false;
                visibleCount--;
            }
            if (visibleCount <= visibleLimit) {
                break;
            }
        }
        return columns;
    };
    ColumnsStore.prototype.isCustomizableVisibleColumn = function (_a) {
        var isVisible = _a.isVisible, isCustomizable = _a.isCustomizable;
        return isVisible && isCustomizable;
    };
    ColumnsStore.prototype.canBeHidden = function (_a) {
        var isVisible = _a.isVisible, isCustomizable = _a.isCustomizable, isRequired = _a.isRequired, isAvailable = _a.isAvailable;
        return isVisible && isCustomizable && !isRequired && isAvailable();
    };
    /**
     * Add additional columns using this logic:
     * it should be placed at the end column's list, but before the last non editable column.
     *
     * @param {Object[]} columns
     * @param {Object[]} additionalColumns
     * @return {Object[]}
     */
    ColumnsStore.prototype.addExtraColumns = function (columns, additionalColumns) {
        // Find insertion position
        var insertAt = _.findLastIndex(columns, function (item) { return item.isCustomizable; });
        insertAt = Math.max(insertAt, 0);
        columns.splice.apply(columns, [insertAt + 1, 0].concat(additionalColumns));
        columns = this.setupItemsPosition(columns);
        return columns;
    };
    ColumnsStore.prototype.loadAll = function () {
        var defaults = this.getFromDefaults();
        var savedItems = (loadState(this.stateName) || []).map(function (_a) {
            var id = _a.id, position = _a.position, isVisible = _a.isVisible;
            return ({
                id: id,
                position: position,
                isVisible: isVisible
            });
        });
        var items = this.mergeItemsWithDefaults(savedItems, defaults);
        return Promise.resolve(items);
    };
    ColumnsStore.prototype.save = function () {
        var items = this.getRawData()
            .filter(function (_a) {
            var isAvailable = _a.isAvailable;
            return isAvailable();
        })
            .map(function (_a) {
            var id = _a.id, position = _a.position, isVisible = _a.isVisible;
            return ({ id: id, position: position, isVisible: isVisible });
        });
        saveState(this.stateName, items);
    };
    ColumnsStore.prototype.getGridColumns = function (filterByShortView) {
        if (filterByShortView === void 0) { filterByShortView = false; }
        return this.getSorted(this.getRawData()).filter(function (_a) {
            var isVisible = _a.isVisible, isAvailable = _a.isAvailable, isForShortView = _a.isForShortView;
            var result = isVisible && isAvailable();
            if (filterByShortView) {
                result = result && isForShortView;
            }
            return result;
        });
    };
    return ColumnsStore;
}(Store));
export { ColumnsStore };
var loadState = function (key) {
    var str = localStorage.getItem(key);
    var result = undefined;
    if (!_.isNil(str)) {
        try {
            result = JSON.parse(str);
        }
        catch (e) {
            result = undefined;
        }
    }
    return result;
};
var saveState = function (storageKey, items) {
    localStorage.setItem(storageKey, JSON.stringify(items));
};
//# sourceMappingURL=ColumnsStore.js.map