export class GradeSchool {
  private _roster: Record<number, string[]> = {};

  roster(): Record<number, string[]> {
    return JSON.parse(JSON.stringify(this._roster));
  }

  get grades(): number[] {
    return Object.keys(this._roster) as unknown as number[];
  }

  add(name: string, grade: number): void {
    const addUniqueValue = <T extends any>(
      array: T[] | undefined,
      value: T
    ): T[] => [...new Set<T>([...(array || []), value])];

    const allGrades = addUniqueValue(this.grades, grade);

    this._roster = allGrades.reduce(
      (newRoster, rosterGrade) => ({
        ...newRoster,
        [rosterGrade]:
          rosterGrade === grade
            ? addUniqueValue(newRoster[rosterGrade], name).sort()
            : newRoster[rosterGrade].filter((n) => n !== name),
      }),
      this._roster
    );
  }

  grade(grade: number): string[] {
    return this.roster()[grade] || [];
  }
}
