import { isEqual } from 'lodash'; import { generate as shortid } from 'shortid'; import { ConfigSettings } from '../types'; export type LayerStackPriority = 'high' | 'low' | number; export interface LayerStackEntry { id: string; item: TItem; priority: LayerStackPriority; sequence: number; tags?: string[]; } /** * Compares ConfigSettingsStackLayer with lowest priority is lowest index. * Order first by priority property value, 'low' first, then integer values high to low (i.e. 1 is highest priority and last in sorted array), * then 'high' prioritiest last. For matching priority property values, order by sequence value. * @param a first layer to compare * @param b second layer to compare */ const compareLayer = (a: LayerStackEntry, b: LayerStackEntry): number => { if (a.priority === b.priority) { return a.sequence - b.sequence; } if (a.priority === 'high' || b.priority === 'low') { return 1; } if (a.priority === 'low' || b.priority === 'high') { return -1; } return (b.priority as number) - (a.priority as number); }; export class LayerStack { private _entries: Array> = []; private _nextSequence = 1; public add(item: TItem, priority: LayerStackPriority = 'high', tags?: string | string[]): LayerStackEntry { const layer: LayerStackEntry = { id: shortid(), item, priority, sequence: this._nextSequence++, tags: tags ? (Array.isArray(tags) ? tags : [tags]) : [], }; this._entries.push(layer); return layer; } public get entries(): Array> { return this._entries.sort(compareLayer); } public getEntries(filter: (entry: LayerStackEntry) => boolean) { return this.entries.filter(filter); } public getItems(filter: (entry: LayerStackEntry) => boolean) { return this.entries.filter(filter); } public getItemsByTag(tags: string | string[], matchType: 'and' | 'or' = 'or') { const aTags = Array.isArray(tags) ? tags : [tags]; return this.entries.filter(l => { return matchType === 'and' ? aTags.every(t => l.tags.indexOf(t) >= 0) : aTags.some(t => l.tags.indexOf(t) >= 0); }); } private getItemsFromEntries = (entries: Array> = this.entries) => { return entries.map(l => l.item); }; public get items(): TItem[] { return this.getItemsFromEntries(); } }