import type { RMap } from '@rimbu/collection-types'; import { Token } from '@rimbu/base'; import { OptLazy, OptLazyOr, type RelatedTo, type ToJSON } from '@rimbu/common'; import { Stream, type StreamSource } from '@rimbu/stream'; import type { ValuedGraphBase, ValuedGraphTypesContextImpl, } from '@rimbu/graph/custom'; import type { WithGraphValues } from '../../common/index.mjs'; import { GraphEmptyBase } from '../../common/index.mjs'; export class ValuedGraphEmpty< N, V, Tp extends ValuedGraphTypesContextImpl, TpG extends WithGraphValues = WithGraphValues, > extends GraphEmptyBase implements ValuedGraphBase { _NonEmptyType!: TpG['nonEmpty']; constructor( readonly isDirected: boolean, readonly context: TpG['context'] ) { super(); } get linkMap(): TpG['linkMap'] { return this.context.linkMapContext.empty(); } getValue( node1: RelatedTo, node2: RelatedTo, otherwise?: OptLazy ): O { return OptLazy(otherwise!); } getConnectionsFrom(): TpG['linkConnections'] { return this.context.linkConnectionsContext.empty(); } addNode(node: N): TpG['nonEmpty'] { return this.context.createNonEmpty( this.linkMap.context.of([ node, this.context.linkConnectionsContext.empty(), ]), 0 ); } addNodes(nodes: StreamSource): WithGraphValues['nonEmpty'] { const emptyConnections = this.context.linkConnectionsContext.empty(); const linkMap = this.context.linkMapContext.from( Stream.from(nodes).map((node) => [node, emptyConnections]) ); if (!linkMap.nonEmpty()) return this as any; return this.context.createNonEmpty(linkMap, 0) as TpG['nonEmpty']; } connect(node1: N, node2: N, value: V): TpG['nonEmpty'] { const linkMap = this.context.linkMapContext.of([ node1, this.context.linkConnectionsContext.of([node2, value]) as RMap, ]) as RMap.NonEmpty>; if (node1 === node2) return this.context.createNonEmpty(linkMap, 1); const linkConnections = this.isDirected ? this.context.linkConnectionsContext.empty() : this.context.linkConnectionsContext.of([node1, value]); return this.context.createNonEmpty(linkMap.set(node2, linkConnections), 1); } connectAll( links: StreamSource['link']> ): WithGraphValues['nonEmpty'] { return this.context.from(links); } modifyAt( node1: N, node2: N, options: { ifNew?: OptLazyOr; ifExists?: (value: V, remove: Token) => V | Token; } ): WithGraphValues['normal'] { if (undefined === options.ifNew) return this as any; const newValue = OptLazyOr(options.ifNew, Token); if (Token === newValue) return this as any; return this.connect(node1, node2, newValue); } mapValues(): WithGraphValues['normal'] { return this as any; } toString(): string { return `${this.context.typeTag}()`; } toJSON(): ToJSON { return { dataType: this.context.typeTag, value: [], }; } toBuilder(): TpG['builder'] { return this.context.builder(); } }