"use strict";

var __importDefault = this && this.__importDefault || function(mod) {
    return mod && mod.__esModule ? mod : {
        default: mod
    };
};

Object.defineProperty(exports, "__esModule", {
    value: !0
}), exports.CachedDataSource = void 0;

const vutils_1 = require("@visactor/vutils"), ts_types_1 = require("../ts-types"), DataSource_1 = require("./DataSource"), get_1 = __importDefault(require("lodash/get"));

function _setFieldCache(fCache, index, field, value) {
    (fCache[index] || (fCache[index] = new Map)).set(field, value);
}

class CachedDataSource extends DataSource_1.DataSource {
    static get EVENT_TYPE() {
        return DataSource_1.DataSource.EVENT_TYPE;
    }
    static ofArray(array, dataConfig, pagination, columns, rowHierarchyType, hierarchyExpandLevel) {
        return new CachedDataSource({
            get: index => array[index],
            length: array.length,
            records: array
        }, dataConfig, pagination, columns, rowHierarchyType, hierarchyExpandLevel);
    }
    constructor(opt, dataConfig, pagination, columns, rowHierarchyType, hierarchyExpandLevel) {
        let _isGrouped;
        (0, vutils_1.isArray)(null == dataConfig ? void 0 : dataConfig.groupByRules) && (_isGrouped = !0), 
        super(opt, dataConfig, pagination, columns, rowHierarchyType, hierarchyExpandLevel), 
        this._isGrouped = _isGrouped, this._recordCache = [], this._fieldCache = {};
    }
    getOriginalRecord(index) {
        return (0, vutils_1.isNumber)(index) && this._recordCache && this._recordCache[index] ? this._recordCache[index] : super.getOriginalRecord(index);
    }
    getRawRecord(index) {
        var _a, _b, _c, _d;
        let originRecordIndex, data;
        if (this._isGrouped) {
            if (originRecordIndex = this.getOriginRecordIndexForGroup(index), (0, vutils_1.isValid)(originRecordIndex) && (null === (_a = this.beforeChangedRecordsMap) || void 0 === _a ? void 0 : _a.has(originRecordIndex.toString()))) return null === (_b = this.beforeChangedRecordsMap) || void 0 === _b ? void 0 : _b.get(originRecordIndex.toString());
        } else if (null === (_c = this.beforeChangedRecordsMap) || void 0 === _c ? void 0 : _c.has(index.toString())) return null === (_d = this.beforeChangedRecordsMap) || void 0 === _d ? void 0 : _d.get(index.toString());
        return (0, vutils_1.isNumber)(index) && this._recordCache && this._recordCache[index] ? this._recordCache[index] : (data = this.dataSourceObj.records ? Array.isArray(index) ? (0, 
        DataSource_1.getValueFromDeepArray)(this.records, index) : this.records[index] : this._get(index), 
        (0, DataSource_1.getValue)(data, (val => {
            this.recordPromiseCallBack(index, val);
        })));
    }
    getOriginalField(index, field, col, row, table) {
        const rowCache = this._fieldCache && this._fieldCache[index];
        if (rowCache) {
            const cache = rowCache.get(field);
            if (cache) return cache;
        }
        return super.getOriginalField(index, field, col, row, table);
    }
    clearCache() {
        this._recordCache && (this._recordCache = []), this._fieldCache && (this._fieldCache = {});
    }
    fieldPromiseCallBack(index, field, value) {
        _setFieldCache(this._fieldCache, index, field, value);
    }
    recordPromiseCallBack(index, record) {
        this._recordCache && (this._recordCache[index] = record);
    }
    get records() {
        return Array.isArray(this._recordCache) && this._recordCache.length > 0 ? this._recordCache : super.records;
    }
    release() {
        var _a;
        null === (_a = super.release) || void 0 === _a || _a.call(this), this._recordCache = null, 
        this._fieldCache = null;
    }
    _generateFieldAggragations() {
        var _a;
        if (super._generateFieldAggragations(), (0, vutils_1.isArray)(null === (_a = this.dataConfig) || void 0 === _a ? void 0 : _a.groupByRules)) {
            const groupByKeys = this.dataConfig.groupByRules;
            this.groupAggregator = new this.registedAggregators[ts_types_1.AggregationType.CUSTOM]({
                field: "",
                aggregationFun: (values, records, field) => {
                    const groupMap = new Map, groupResult = [];
                    for (let i = 0; i < records.length; i++) dealWithGroup(records[i], groupResult, groupMap, groupByKeys, 0);
                    return groupResult;
                }
            }), this.fieldAggregators.push(this.groupAggregator);
        }
    }
    processRecords(records) {
        var _a;
        const result = super.processRecords(records), groupResult = null === (_a = this.groupAggregator) || void 0 === _a ? void 0 : _a.value();
        return groupResult || result;
    }
    getGroupLength() {
        var _a, _b, _c;
        return null !== (_c = null === (_b = null === (_a = this.dataConfig) || void 0 === _a ? void 0 : _a.groupByRules) || void 0 === _b ? void 0 : _b.length) && void 0 !== _c ? _c : 0;
    }
    updateGroup() {
        var _a, _b, _c;
        this.clearCache();
        const oldSource = this.source;
        this._source = this.processRecords(null !== (_b = null === (_a = this.dataSourceObj) || void 0 === _a ? void 0 : _a.records) && void 0 !== _b ? _b : this.dataSourceObj), 
        oldSource && syncGroupCollapseState(oldSource, this.source), this.sourceLength = (null === (_c = this.source) || void 0 === _c ? void 0 : _c.length) || 0, 
        this.sortedIndexMap.clear(), this.currentIndexedData = Array.from({
            length: this.sourceLength
        }, ((_, i) => i)), this.userPagination || (this.pagination.perPageCount = this.sourceLength, 
        this.pagination.totalCount = this.sourceLength), this.initTreeHierarchyState(), 
        this.updatePagerData();
    }
    getOriginRecordIndexForGroup(recordIndex) {
        const targetRecord = this.getOriginalRecord(recordIndex);
        if ((0, vutils_1.isValid)(targetRecord) && !(targetRecord.children && targetRecord.children.length > 0)) for (let i = 0; i < this.dataSourceObj.records.length; i++) if (this.dataSourceObj.records[i] === targetRecord) return i;
    }
    addRecordsForGroup(recordArr, recordIndex) {
        if (!(0, vutils_1.isArray)(recordArr) || 0 === recordArr.length) return;
        let originRecordIndex = this.getOriginRecordIndexForGroup(recordIndex);
        (void 0 === originRecordIndex || originRecordIndex > this.dataSourceObj.records) && (originRecordIndex = this.dataSourceObj.records.length), 
        this.dataSourceObj.records.splice(originRecordIndex, 0, ...recordArr), this.adjustBeforeChangedRecordsMap(originRecordIndex, recordArr.length), 
        this.updateGroup();
    }
    deleteRecordsForGroup(recordIndexs) {
        if (!(0, vutils_1.isArray)(recordIndexs) || 0 === recordIndexs.length) return;
        const recordIndexsMaxToMin = (0, DataSource_1.sortRecordIndexs)(recordIndexs, -1);
        for (let index = 0; index < recordIndexsMaxToMin.length; index++) {
            const recordIndex = recordIndexsMaxToMin[index];
            if ((0, vutils_1.isNumber)(recordIndex) && (recordIndex >= this.sourceLength || recordIndex < 0)) continue;
            const originRecordIndex = this.getOriginRecordIndexForGroup(recordIndex);
            this.beforeChangedRecordsMap.delete(originRecordIndex.toString()), this.dataSourceObj.records.splice(originRecordIndex, 1), 
            this.sourceLength -= 1, this.adjustBeforeChangedRecordsMap(originRecordIndex, 1, "delete");
        }
        this.updateGroup();
    }
    updateRecordsForGroup(records, recordIndexs) {
        for (let index = 0; index < recordIndexs.length; index++) {
            const recordIndex = recordIndexs[index];
            if ((0, vutils_1.isNumber)(recordIndex) && (recordIndex >= this.sourceLength || recordIndex < 0)) continue;
            const originRecordIndex = this.getOriginRecordIndexForGroup(recordIndex);
            this.beforeChangedRecordsMap.delete(originRecordIndex.toString()), this.dataSourceObj.records[originRecordIndex] = records[index];
        }
        this.updateGroup();
    }
    addRecordsForTree(recordArr, recordIndex) {
        if ((0, vutils_1.isArray)(recordArr) && 0 !== recordArr.length) {
            if (this.adjustBeforeChangedRecordsMap(recordIndex, recordArr.length), (0, vutils_1.isNumber)(recordIndex)) this.dataSourceObj.records.splice(recordIndex, 0, ...recordArr); else {
                const recordIndex_copy = [ ...recordIndex ], index = recordIndex_copy.pop(), parentRecord = this.getOriginalRecord(recordIndex_copy);
                parentRecord.children ? parentRecord.children.splice(index, 0, ...recordArr) : parentRecord.children = recordArr;
            }
            this.initTreeHierarchyState(), this.updatePagination();
        }
    }
    deleteRecordsForTree(recordIndexs) {
        if (!(0, vutils_1.isArray)(recordIndexs) || 0 === recordIndexs.length) return [];
        const recordIndexsMaxToMin = (0, DataSource_1.sortRecordIndexs)(recordIndexs, -1), deletedRecordIndexs = [];
        for (let index = 0; index < recordIndexsMaxToMin.length; index++) {
            const recordIndex = recordIndexsMaxToMin[index];
            if (!(0, vutils_1.isNumber)(recordIndex) || !(recordIndex >= this.sourceLength || recordIndex < 0)) {
                if (this.beforeChangedRecordsMap.delete(recordIndex.toString()), (0, vutils_1.isNumber)(recordIndex)) this.dataSourceObj.records.splice(recordIndex, 1); else {
                    const recordIndex_copy = [ ...recordIndex ], index = recordIndex_copy.pop();
                    this.getOriginalRecord(recordIndex_copy).children.splice(index, 1);
                }
                this.adjustBeforeChangedRecordsMap(recordIndex, 1, "delete"), deletedRecordIndexs.push(recordIndex);
            }
        }
        return this.initTreeHierarchyState(), this.updatePagination(), deletedRecordIndexs;
    }
    updateRecordsForTree(records, recordIndexs) {
        for (let index = 0; index < recordIndexs.length; index++) {
            const recordIndex = recordIndexs[index], record = records[index];
            if (!(0, vutils_1.isNumber)(recordIndex) || !(recordIndex >= this.sourceLength || recordIndex < 0)) if (this.beforeChangedRecordsMap.delete(recordIndex.toString()), 
            (0, vutils_1.isNumber)(recordIndex)) this.dataSourceObj.records.splice(recordIndex, 1, record); else {
                const recordIndex_copy = [ ...recordIndex ], index = recordIndex_copy.pop();
                this.getOriginalRecord(recordIndex_copy).children.splice(index, 1, record);
            }
        }
        this.initTreeHierarchyState(), this.updatePagerData();
    }
    adjustBeforeChangedRecordsMap(insertIndex, insertCount, type = "add") {
        if ("tree" === this.rowHierarchyType) {
            let insertIndexArr;
            insertIndexArr = (0, vutils_1.isNumber)(insertIndex) ? [ insertIndex ] : insertIndex;
            const targetResult = [];
            this.beforeChangedRecordsMap.forEach(((value, key) => {
                var _a, _b;
                const keyArray = key.split(","), length = Math.max(keyArray.length, insertIndexArr.length);
                for (let i = 0; i < length; i++) {
                    const current = null !== (_a = insertIndexArr[i]) && void 0 !== _a ? _a : -1, keyIndex = null !== (_b = Number(keyArray[i])) && void 0 !== _b ? _b : -1;
                    if (current < keyIndex || current === keyIndex && i === keyArray.length - 1 && i === insertIndexArr.length - 1) return keyArray[i] = (keyIndex + ("add" === type ? insertCount : -insertCount)).toString(), 
                    void targetResult.push({
                        originKey: key,
                        targetKey: keyArray.toString(),
                        value: value
                    });
                }
            })), targetResult.forEach((({originKey: originKey, targetKey: targetKey, value: value}) => {
                this.beforeChangedRecordsMap.delete(originKey), this.beforeChangedRecordsMap.set(targetKey, value);
            }));
        } else super.adjustBeforeChangedRecordsMap(insertIndex, insertCount, type);
    }
    cacheBeforeChangedRecord(dataIndex, table) {
        var _a;
        const originRecord = this.getOriginalRecord(dataIndex);
        table.internalProps.groupBy && (dataIndex = this.getOriginRecordIndexForGroup(dataIndex)), 
        this.beforeChangedRecordsMap.has(dataIndex.toString()) || this.beforeChangedRecordsMap.set(dataIndex.toString(), null !== (_a = (0, 
        vutils_1.cloneDeep)(originRecord, void 0, [ "vtable_gantt_linkedFrom", "vtable_gantt_linkedTo" ])) && void 0 !== _a ? _a : {});
    }
    getGroupSeriesNumber(showIndex) {
        const recordIndex = this.dataSource.currentIndexedData[showIndex], parentRecordIndexLength = recordIndex.length - 1;
        let recordIndexLength = recordIndex.length, i = 1;
        for (;recordIndexLength > parentRecordIndexLength; i++) {
            const index = this.dataSource.currentIndexedData[showIndex - i];
            recordIndexLength = (0, vutils_1.isNumber)(index) ? 1 : index.length;
        }
        return i - 1;
    }
}

function dealWithGroup(record, children, map, groupByKeys, level) {
    const groupByKey = groupByKeys[level];
    if (!(0, vutils_1.isValid)(groupByKey)) return void children.push(record);
    const value = (0, get_1.default)(record, groupByKey);
    if (void 0 !== value) {
        if (map.has(value)) {
            const index = map.get(value);
            return dealWithGroup(record, children[index].children, children[index].map, groupByKeys, level + 1);
        }
        return map.set(value, children.length), children.push({
            vtableMerge: !0,
            vtableMergeName: value,
            children: [],
            map: new Map
        }), dealWithGroup(record, children[children.length - 1].children, children[children.length - 1].map, groupByKeys, level + 1);
    }
}

function syncGroupCollapseState(oldSource, newSource, oldGroupMap, newGroupMap) {
    if (!oldGroupMap) {
        oldGroupMap = new Map;
        for (let i = 0; i < oldSource.length; i++) {
            const record = oldSource[i];
            record.vtableMerge && oldGroupMap.set(record.vtableMergeName, i);
        }
    }
    if (!newGroupMap) {
        newGroupMap = new Map;
        for (let i = 0; i < newSource.length; i++) {
            const record = newSource[i];
            record.vtableMerge && newGroupMap.set(record.vtableMergeName, i);
        }
    }
    for (let i = 0; i < oldSource.length; i++) {
        const oldRecord = oldSource[i], newRecord = newSource[newGroupMap.get(oldRecord.vtableMergeName)];
        (0, vutils_1.isValid)(newRecord) && (newRecord.hierarchyState = oldSource[i].hierarchyState), 
        (0, vutils_1.isArray)(null == oldRecord ? void 0 : oldRecord.children) && (0, vutils_1.isArray)(null == newRecord ? void 0 : newRecord.children) && 0 !== oldRecord.map.size && 0 !== newRecord.map.size && syncGroupCollapseState(oldRecord.children, newRecord.children, oldRecord.map, newRecord.map);
    }
}

//# sourceMappingURL=CachedDataSource.js.map
exports.CachedDataSource = CachedDataSource;