/*
 * Copyright (C) 2022 StApps
 * This program is free software: you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the Free
 * Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program. If not, see <https://www.gnu.org/licenses/>.
 */
import {Component, DestroyRef, inject, Input, OnInit} from '@angular/core';
import {SCDateSeries, SCUuid} from '@openstapps/core';
import moment from 'moment';
import {materialFade} from '../../../animation/material-motion';
import {ScheduleProvider} from '../../calendar/schedule.provider';
import {ScheduleEvent} from './schema/schema';
import {groupBy, omit, stringSortBy} from '@openstapps/collection-utils';
import {takeUntilDestroyed} from '@angular/core/rxjs-interop';

/**
 * A single event
 */
export interface ScheduleSingleEvent {
  /**
   * Day the event is on
   */
  day: string;

  /**
   * The event the date is referring to
   */
  event: ScheduleEvent;
}

/**
 * Component that displays single events one after each other
 */
@Component({
  selector: 'stapps-single-events',
  templateUrl: 'schedule-single-events.html',
  styleUrls: ['schedule-single-events.scss'],
  animations: [materialFade],
})
export class ScheduleSingleEventsComponent implements OnInit {
  /**
   * The events to display
   */
  private uuids: SCUuid[];

  /**
   * Events that are displayed
   */
  events: Promise<ScheduleSingleEvent[][]>;

  /**
   * Scale of the view
   */
  @Input() scale = 60;

  destroy$ = inject(DestroyRef);

  /**
   * Sorts dates to a list of days with events on each
   */
  static groupDateSeriesToDays(dateSeries: SCDateSeries[]): ScheduleSingleEvent[][] {
    return Object.entries(
      groupBy(
        dateSeries
          .flatMap(event =>
            event.dates.map(date => ({
              dateUnix: moment(date).unix(),
              day: moment(date).startOf('day').toISOString(),
              event: {
                dateSeries: event,
                time: {
                  start:
                    moment(date).hour() +
                    moment(date)
                      // tslint:disable-next-line:no-magic-numbers
                      .minute() /
                      60,
                  startAsString: moment(date).format('LT'),
                  duration: event.duration,
                  endAsString: moment(date).add(event.duration).format('LT'),
                },
              },
            })),
          )
          .sort((a, b) => a.dateUnix - b.dateUnix)
          .map(event => omit(event, 'dateUnix')),
        it => it.day,
      ),
    )
      .sort(stringSortBy(([key]) => key))
      .map(([_, value]) => value);
  }

  constructor(protected readonly scheduleProvider: ScheduleProvider) {}

  /**
   * Fetch date series items
   */
  async fetchDateSeries(): Promise<ScheduleSingleEvent[][]> {
    // TODO: only single events
    const dateSeries = await this.scheduleProvider.getDateSeries(
      this.uuids,
      undefined /*TODO*/,
      moment(moment.now()).startOf('week').toISOString(),
    );

    // TODO: replace with filter
    return ScheduleSingleEventsComponent.groupDateSeriesToDays(
      dateSeries.dates.filter(it => !it.repeatFrequency),
    );
  }

  ngOnInit() {
    this.scheduleProvider.uuids$.pipe(takeUntilDestroyed(this.destroy$)).subscribe(async result => {
      this.uuids = result;
      this.events = this.fetchDateSeries();
    });
  }
}
