import { HandlerType, SyncFlags } from "../../common/sync/constants.js";
import Receiver from "./receiver.js";
import MapReceiver from "./map-receiver.js";
import CollectionReceiver from "./collection-receiver.js";
import { decode } from "../../common/sync/protocol.js";
class State {
/**
* client state
* @example
* let state = new State();
*/
constructor() {
this.receivers = new Map();
this.queued_changes = new Map();
//init root receiver
let root_receiver = new Receiver(0, this, this);
this[SyncFlags.INSTANCE] = root_receiver;
this.receivers.set(0, root_receiver);
}
addReceiver(id, type) {
let target;
let receiver;
switch (type) {
case HandlerType.MAP:
target = new Map();
receiver = new MapReceiver(id, target, this);
break;
case HandlerType.COLLECTION:
target = [];
receiver = new CollectionReceiver(id, target, this);
break;
default:
target = {};
receiver = new Receiver(id, target, this);
break;
}
target[SyncFlags.INSTANCE] = receiver;
this.receivers.set(id, receiver);
return target;
}
deleteReceiver(id) {
let r = this.receivers.get(id);
r.children.forEach(child => {
this.deleteReceiver(child[SyncFlags.INSTANCE].id);
});
this.receivers.delete(id);
}
update(changes) {
if (!changes.length) return;
if (!isNaN(changes[0])) {
changes = decode(changes);
}
let updated_receivers = new Set();
changes.forEach(c => {
if (!this.receivers.has(c.ref)) {
//we received a change from a ref we do not know yet, store it for later
let queued = this.queued_changes.get(c.ref);
if (!queued) {
queued = [];
this.queued_changes.set(c.ref, queued);
}
queued.push(c);
if (queued.length > 500) {
console.warn("Queued over 500 changes for unknown ref id " + c.ref);
}
return;
}
updated_receivers.add(c.ref);
this.receivers.get(c.ref).receive(c);
});
updated_receivers.forEach(ref => {
if (!this.receivers.has(ref)) return;
this.receivers.get(ref).flushStoredEvents();
})
}
}
export default State