import {MatchRankFunction} from '../types/MatchRankFunction'; import {RankSort} from './RankSort'; import {RankFunction} from '../types/RankFunction'; import {SearchListIndex} from './SearchListIndex'; import {BooleanMatchFunction} from '../types/BooleanMatchFunction'; import {SearchFunction} from '../types/SearchFunction'; import {listRankFunction} from '../utils/listRankFunction'; export class MatchSort { private matchRankFunctionList: MatchRankFunction[]; private filter: BooleanMatchFunction = () => () => true; private searchListIndex: SearchListIndex; constructor() { this.matchRankFunctionList = []; this.searchListIndex = new SearchListIndex(this.searchFunction); } private searchFunction: SearchFunction = (search: string, values: T[]) => { const filteredValues = values.filter(this.filter(search)); return this.makeSorter(search).sort(filteredValues); } public makeSorter(search: string): RankSort { return new RankSort(this.makeRankFunctions(search)); } private makeRankFunctions = (search: string): RankFunction[] => { return this.matchRankFunctionList.map((matchRankFunction) => matchRankFunction(search)); } public chain(rankFunction: MatchRankFunction): MatchSort { this.matchRankFunctionList.push(rankFunction); return this; } public setMatchRankFunctionList(matchRankFunctionList: MatchRankFunction[]): MatchSort { this.matchRankFunctionList = matchRankFunctionList; return this; } public setFilter(filter: BooleanMatchFunction): MatchSort { this.filter = filter; return this; } public sort(search: string, values: T[]): T[] { return this.searchListIndex.run(values, search); } public onProperty

(property: P): MatchSort { const newMatcher = new MatchSort(); const convertRankFunction = (matchRankFunction: MatchRankFunction) => (search: string) => (value: O) => matchRankFunction(search)(value[property]); const newRankFunctions = this .matchRankFunctionList .map(convertRankFunction); newMatcher.setMatchRankFunctionList(newRankFunctions); const newFilter = (search: string) => (value: O) => this.filter(search)(value[property]); newMatcher.setFilter(newFilter); return newMatcher; } public onList(): MatchSort { const newMatcher = new MatchSort(); const convertRankFunction = (matchRankFunction: MatchRankFunction) => (search: string) => { const rankFunction = matchRankFunction(search); return listRankFunction(rankFunction); }; const newRankFunctions = this .matchRankFunctionList .map(convertRankFunction); newMatcher.setMatchRankFunctionList(newRankFunctions); const newFilter = (search: string) => (values: T[]) => values.some(this.filter(search)); newMatcher.setFilter(newFilter); return newMatcher; } }