import { AbstractStateful } from "@/core/stateful/abstract.stateful" export type StatefulSubscriber = (value: T) => void export type StatefulSetter = (value: T) => T export class Stateful implements AbstractStateful { private _subscribers: Set> = new Set() private _version: number = 0 public constructor(private _value: T) { this.Notify() } public Get(): T { return this._value } public If(predicate: (value: T) => boolean, then: (value: T) => U, otherwise: (value: T) => U, factory: (value: U) => Stateful = v => new Stateful(v)): Stateful { const derived = factory(predicate(this._value) ? then(this._value) : otherwise(this._value)) this.Subscribe(value => derived.Set(() => predicate(value) ? then(value) : otherwise(value))) return derived } public DirectSet(value: T): void { this._value = value this._version++ this.Notify() } public Set(fabric: StatefulSetter): void { this.DirectSet(fabric(this._value)) } public Subscribe(subscriber: StatefulSubscriber): () => void { this._subscribers.add(subscriber) return () => this._subscribers.delete(subscriber) } public Notify(): void { for (const subscriber of this._subscribers) { subscriber(this._value) } } public Dispose(): void { this._subscribers.clear() this._version = 0 } public get Value(): T { return this.Get() } public get Version(): number { return this._version } }