/*
 * Copyright (C) 2021 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, Input, OnDestroy, OnInit} from '@angular/core';
import {SCDateSeries, SCUuid} from '@openstapps/core';
import {flatMap, groupBy, isNil, omit, sortBy} from 'lodash-es';
import moment from 'moment';
import {Subscription} from 'rxjs';
import {materialFade} from '../../../animation/material-motion';
import {ScheduleProvider} from '../../calendar/schedule.provider';
import {ScheduleEvent} from './schema/schema';

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

  /**
   * 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, OnDestroy {
  /**
   * UUID subscription
   */
  private _uuidSubscription: Subscription;

  /**
   * The events to display
   */
  private uuids: SCUuid[];

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

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

  /**
   * Sorts dates to a list of days with events on each
   */
  static groupDateSeriesToDays(
    dateSeries: SCDateSeries[],
  ): ScheduleSingleEvent[][] {
    return sortBy(
      groupBy(
        flatMap(dateSeries, 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,
                duration: event.duration,
              },
            },
          })),
        )
          .sort((a, b) => a.dateUnix - b.dateUnix)
          .map(event => omit(event, 'dateUnix')),
        'day',
      ),
      'day',
    );
  }

  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 => isNil(it.repeatFrequency)),
    );
  }

  /**
   * OnDestroy
   */
  ngOnDestroy(): void {
    this._uuidSubscription.unsubscribe();
  }

  /**
   * Initialize
   */
  ngOnInit() {
    this._uuidSubscription = this.scheduleProvider.uuids$.subscribe(
      async result => {
        this.uuids = result;
        this.events = this.fetchDateSeries();
      },
    );
  }
}
