"use strict";
var __values = (this && this.__values) || function(o) {
    var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
    if (m) return m.call(o);
    if (o && typeof o.length === "number") return {
        next: function () {
            if (o && i >= o.length) o = void 0;
            return { value: o && o[i++], done: !o };
        }
    };
    throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
};
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
var realtime_subscriptions_1 = __importDefault(require("../realtime-subscriptions"));
var object_merger_1 = require("./object-merger");
var StorableRealtimeSubscriptions = /** @class */ (function () {
    function StorableRealtimeSubscriptions(session, dataStore, storableDataService) {
        this.realtimeSubscriptions = new realtime_subscriptions_1.default(session);
        this.dataStore = dataStore;
        this.storableDataService = storableDataService;
        this.eventCallbacks = {};
    }
    StorableRealtimeSubscriptions.prototype.updateStoreOnEvents = function (events, subEntityEvents) {
        var e_1, _a, e_2, _b;
        var _this = this;
        if (subEntityEvents === void 0) { subEntityEvents = []; }
        var _loop_1 = function (event_1) {
            this_1.realtimeSubscriptions.subscribe(event_1.name, function (item) {
                item = event_1.itemExtractor ? event_1.itemExtractor(item) : item;
                var data = event_1.extraDataFunc && event_1.extraDataFunc(item);
                if (data === null || data === void 0 ? void 0 : data.ignore) {
                    return;
                }
                if (event_1.isDelete) {
                    if (!_this.dataStore.get(item.id)) {
                        return;
                    }
                    var deletedItem = _this.storableDataService.removeFromStores(item.id);
                    _this.runEventCallbacks(event_1.name, { diff: deletedItem });
                }
                else {
                    var skipStoreUpdate = !!(data === null || data === void 0 ? void 0 : data.skipStoreUpdate);
                    if (skipStoreUpdate) {
                        var mappedStorableItem = _this.storableDataService.mapItem(item, data === null || data === void 0 ? void 0 : data.params);
                        _this.runEventCallbacks(event_1.name, mappedStorableItem, { skipStoreUpdate: skipStoreUpdate });
                    }
                    else {
                        var mappedStorableItem = _this.storableDataService.updateInStores(item, undefined, undefined, data === null || data === void 0 ? void 0 : data.params);
                        _this.runEventCallbacks(event_1.name, mappedStorableItem);
                    }
                }
            });
        };
        var this_1 = this;
        try {
            for (var events_1 = __values(events), events_1_1 = events_1.next(); !events_1_1.done; events_1_1 = events_1.next()) {
                var event_1 = events_1_1.value;
                _loop_1(event_1);
            }
        }
        catch (e_1_1) { e_1 = { error: e_1_1 }; }
        finally {
            try {
                if (events_1_1 && !events_1_1.done && (_a = events_1.return)) _a.call(events_1);
            }
            finally { if (e_1) throw e_1.error; }
        }
        var _loop_2 = function (subEntityEvent) {
            this_2.realtimeSubscriptions.subscribe(subEntityEvent.name, function (subEntityEventData) {
                subEntityEvent.ignoreFields.forEach(function (field) { return delete subEntityEventData[field]; });
                var eventChangeData = _this.changeSubEntity(subEntityEventData, subEntityEvent.idField || 'id', subEntityEvent.parentField, subEntityEvent.field, subEntityEvent.isDelete);
                if (eventChangeData === null || eventChangeData === void 0 ? void 0 : eventChangeData.current) {
                    _this.runEventCallbacks(subEntityEvent.eventToRaise, eventChangeData);
                }
            });
        };
        var this_2 = this;
        try {
            for (var subEntityEvents_1 = __values(subEntityEvents), subEntityEvents_1_1 = subEntityEvents_1.next(); !subEntityEvents_1_1.done; subEntityEvents_1_1 = subEntityEvents_1.next()) {
                var subEntityEvent = subEntityEvents_1_1.value;
                _loop_2(subEntityEvent);
            }
        }
        catch (e_2_1) { e_2 = { error: e_2_1 }; }
        finally {
            try {
                if (subEntityEvents_1_1 && !subEntityEvents_1_1.done && (_b = subEntityEvents_1.return)) _b.call(subEntityEvents_1);
            }
            finally { if (e_2) throw e_2.error; }
        }
    };
    StorableRealtimeSubscriptions.prototype.onAnyEvent = function (event, callback) {
        return this.realtimeSubscriptions.subscribe(event, callback);
    };
    StorableRealtimeSubscriptions.prototype.onEvent = function (event, callback, options) {
        var _this = this;
        if (options === void 0) { options = {}; }
        if (!this.eventCallbacks[event]) {
            this.eventCallbacks[event] = [];
        }
        var entry = { callback: callback, options: options };
        this.eventCallbacks[event].push(entry);
        return function () {
            var index = _this.eventCallbacks[event].indexOf(entry);
            if (index > -1) {
                _this.eventCallbacks[event].splice(index, 1);
            }
        };
    };
    StorableRealtimeSubscriptions.prototype.runEventCallbacks = function (event, data, meta) {
        (this.eventCallbacks[event] || []).forEach(function (entry) {
            if ((meta === null || meta === void 0 ? void 0 : meta.skipStoreUpdate) && entry.options.notifyOnSkippedStoreUpdate !== true) {
                return;
            }
            entry.callback(data);
        });
    };
    StorableRealtimeSubscriptions.prototype.changeSubEntity = function (subEntity, idField, parentField, containerField, isDelete) {
        var _a, _b, _c;
        var current = this.dataStore.get(subEntity[parentField]);
        var diff;
        if (current) {
            var existingIndex = current[containerField]
                ? current[containerField].findIndex(function (taskSubEntity) { return taskSubEntity.id === subEntity[idField]; })
                : -1;
            if (existingIndex > -1) {
                if (isDelete) {
                    diff = (_a = {}, _a[containerField] = this.createArrayOfEmptyObjects(existingIndex), _a);
                    for (var i = existingIndex; i < current[containerField].length; i++) {
                        diff[containerField].push(current[containerField][i]);
                    }
                    current[containerField].splice(existingIndex, 1);
                }
                else {
                    var subEntityDiff = object_merger_1.objectMerger.deepMerge(current[containerField][existingIndex], subEntity);
                    diff = (_b = {},
                        _b[containerField] = this.createArrayOfEmptyObjects(current[containerField].length),
                        _b);
                    diff[containerField][existingIndex] = subEntityDiff;
                }
            }
            else if (!isDelete) {
                if (!current[containerField]) {
                    current[containerField] = [];
                }
                diff = (_c = {},
                    _c[containerField] = this.createArrayOfEmptyObjects(current[containerField].length),
                    _c);
                diff[containerField].push(subEntity);
                current[containerField].push(subEntity);
            }
        }
        if (diff) {
            return { current: current, diff: diff };
        }
    };
    StorableRealtimeSubscriptions.prototype.createArrayOfEmptyObjects = function (length) {
        return Array.from({ length: length }, function () { return ({}); });
    };
    return StorableRealtimeSubscriptions;
}());
exports.default = StorableRealtimeSubscriptions;
//# sourceMappingURL=storable-realtime-subscriptions.js.map