import { from, IEnumerable } from 'ts-linq-light'; import { IGroupingRenderer, RenderContext } from './IGroupingRenderer'; export interface NextFunction { count(items: IEnumerable): number; render(items: IEnumerable): void; } interface RenderLevel { renderer: IGroupingRenderer; items: IEnumerable; } export class RenderBuilder { private levels: RenderLevel[] = []; constructor(private context: RenderContext) {} add(renderer: IGroupingRenderer, items: IEnumerable): this { this.levels.push({ renderer, items }); return this; } getTotalCount(): number { if (this.levels.length === 0) return 0; const chain = this.buildChain(0); return chain.count(this.levels[0].items); } build(): void { if (this.levels.length === 0) return; const chain = this.buildChain(0); chain.render(this.levels[0].items); } private buildChain(index: number): NextFunction { if (index >= this.levels.length) { // Leaf - ingen flere levels return { count: (items) => from(items).count(), render: () => {} }; } const level = this.levels[index]; const nextChain = this.buildChain(index + 1); return { count: (items) => { let total = 0; for (const item of items) { const childItems = this.getChildItems(index, item); total += nextChain.count(childItems); } return total || from(items).count(); }, render: (items) => { level.renderer.render(items, nextChain, this.context); } }; } private getChildItems(levelIndex: number, _parentItem: unknown): IEnumerable { // Returnerer næste levels items - rendereren selv filtrerer baseret på parent const nextLevel = this.levels[levelIndex + 1]; if (!nextLevel) { return from([]); } return nextLevel.items; } }