import {ChangeDetectionStrategy, Component, Input} from '@angular/core';
import {mergeMap, ReplaySubject} from 'rxjs';
import {map} from 'rxjs/operators';
import {SCDateSeries, SCISO8601Date} from '@openstapps/core';
import moment from 'moment/moment';
import {ScheduleProvider} from '../../calendar/schedule.provider';

interface MyCoursesTodayInterface {
  startTime: string;
  endTime: string;
  course: SCDateSeries;
}

type MyCoursesGroup = [SCISO8601Date, MyCoursesTodayInterface[]][];

/**
 * Groups date series into a list of events happening in the next days
 * @param dateSeries the date series to group
 * @param visibleDays the number of days ahead to group
 */
function groupDays(dateSeries: SCDateSeries[], visibleDays: number): MyCoursesGroup {
  const courses: [SCISO8601Date, MyCoursesTodayInterface[]][] = [];
  const dates = Array.from({length: visibleDays}, (_, i) => moment().startOf('day').add(i, 'days'));

  for (const day of dates) {
    const dayCourses: MyCoursesTodayInterface[] = [];
    for (const course of dateSeries) {
      for (const date of course.dates) {
        if (moment(date).isSame(day, 'day')) {
          dayCourses.push({
            startTime: moment(date).toISOString(),
            endTime: moment(date).add(course.duration).toISOString(),
            course,
          });
        }
      }
    }
    courses.push([day.toISOString(), dayCourses]);
  }

  return courses;
}

@Component({
  selector: 'my-courses',
  templateUrl: 'my-courses.html',
  styleUrls: ['my-courses.scss'],
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class MyCoursesComponent {
  /**
   * The number of days from today to display
   */
  @Input({required: true}) set visibleDays(value: number) {
    this.visibleDays$.next(value);
  }

  readonly visibleDays$ = new ReplaySubject<number>();

  myCourses = this.visibleDays$.pipe(
    mergeMap(visibleDays =>
      this.scheduleProvider.uuids$.pipe(
        mergeMap(uuids => this.scheduleProvider.getDateSeries(uuids)),
        map(dateSeries => groupDays(dateSeries.dates, visibleDays)),
      ),
    ),
  );

  constructor(private scheduleProvider: ScheduleProvider) {}
}
