import { Injectable } from '@angular/core'; import { RawYearCode, RawTermCode } from '../shared/term-codes/without-era'; import { YearCode } from '../shared/term-codes/yearcode'; import { TermCode, Era } from '../shared/term-codes/termcode'; @Injectable({ providedIn: 'root' }) export class TermCodeFactory { private state: 'uninitialized' | 'initialized' = 'uninitialized'; public active: ReadonlyArray<TermCode> = []; private static pickEra(code: RawTermCode, active: ReadonlyArray<TermCode>) { const isActive = active.some(t => t.equals(code)); if (isActive) { return Era.Active; } const beforeActive = active.every(t => t.comesAfter(code)); if (beforeActive) { return Era.Past; } else { return Era.Future; } } private requireInitialization() { if (this.isNotInitialized()) { throw new Error('cannot use TermCodeFactory without active terms'); } } public isNotInitialized(): boolean { return this.state !== 'initialized'; } public setActiveTermCodes(active: RawTermCode[]) { if (this.isNotInitialized() === false) { throw new Error('the TermCodeFactory was already initialized'); } else if (active.length === 0) { throw new Error('app cannot have 0 active terms, must have at least 1'); } this.state = 'initialized'; this.active = active .sort(RawTermCode.sort) .map(t => new TermCode(t, Era.Active, this.fromRawYearCode(t.yearCode))); } public first() { return this.active[0]; } public fromString(str: string) { this.requireInitialization(); const raw = new RawTermCode(str); const era = TermCodeFactory.pickEra(raw, this.active); return new TermCode(raw, era, this.fromRawYearCode(raw.yearCode)); } public fromRawYearCode(raw: RawYearCode | string): YearCode { if (typeof raw === 'string') { raw = new RawYearCode(raw); } const fall = TermCodeFactory.pickEra(raw.fall(), this.active); const spring = TermCodeFactory.pickEra(raw.spring(), this.active); const summer = TermCodeFactory.pickEra(raw.summer(), this.active); return new YearCode(raw.toString(), fall, spring, summer); } public fromYear(year: YearCode) { return { fall: this.fromString(`${year.toString()}2`), spring: this.fromString(`${year.toString()}4`), summer: this.fromString(`${year.toString()}6`), }; } }