/*
 * Copyright (C) 2023 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 {
  AfterViewInit,
  Component,
  DestroyRef,
  ElementRef,
  inject,
  NgZone,
  OnDestroy,
  OnInit,
  ViewChild,
} from '@angular/core';
import {Router} from '@angular/router';
import {Location} from '@angular/common';
import moment from 'moment';
import {SCDateSeries, SCUuid} from '@openstapps/core';
import {DataRoutingService} from '../data/data-routing.service';
import {ScheduleProvider} from '../calendar/schedule.provider';
import {AnimationController, IonContent} from '@ionic/angular/standalone';
import {DashboardCollapse} from './dashboard-collapse';
import {BreakpointObserver} from '@angular/cdk/layout';
import {takeUntilDestroyed} from '@angular/core/rxjs-interop';

@Component({
  selector: 'app-dashboard',
  templateUrl: './dashboard.component.html',
  styleUrls: ['./dashboard.component.scss', './dashboard.collapse.component.scss'],
})
export class DashboardComponent implements OnInit, OnDestroy, AfterViewInit {
  @ViewChild('toolbar', {read: ElementRef}) toolbarRef: ElementRef;

  @ViewChild('schedule', {read: ElementRef}) scheduleRef: ElementRef;

  @ViewChild('ionContent') ionContentRef: IonContent;

  collapseAnimation: DashboardCollapse;

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

  /**
   * Next event in calendar
   */
  nextEvent: SCDateSeries | undefined;

  destroy$ = inject(DestroyRef);

  constructor(
    private readonly dataRoutingService: DataRoutingService,
    private scheduleProvider: ScheduleProvider,
    protected router: Router,
    public location: Location,
    private animationControl: AnimationController,
    private breakpointObserver: BreakpointObserver,
    private zone: NgZone,
  ) {
    this.dataRoutingService
      .itemSelectListener()
      .pipe(takeUntilDestroyed())
      .subscribe(item => {
        void this.router.navigate(['data-detail', item.uid], {state: {item}});
      });
  }

  async ngOnInit() {
    this.scheduleProvider.uuids$.pipe(takeUntilDestroyed(this.destroy$)).subscribe(async result => {
      this.eventUuids = result;
      await this.loadNextEvent();
    });
  }

  async ngAfterViewInit() {
    this.collapseAnimation = new DashboardCollapse(
      this.animationControl,
      this.zone,
      await this.ionContentRef.getScrollElement(),
      this.toolbarRef.nativeElement,
      this.scheduleRef.nativeElement,
    );

    this.breakpointObserver
      .observe(['(min-width: 768px)'])
      .pipe(takeUntilDestroyed(this.destroy$))
      .subscribe(async state => {
        await this.collapseAnimation.ready;
        this.collapseAnimation.active = !state.matches;
      });
  }

  async loadNextEvent() {
    const dataSeries = await this.scheduleProvider.getDateSeries(
      this.eventUuids,
      undefined,
      moment(moment.now()).startOf('week').toISOString(),
    );

    this.nextEvent = dataSeries.dates
      .map(series => ({
        time: new Date(
          series.dates
            .sort((a, b) => new Date(a).getTime() - new Date(b).getTime())
            .find(date => new Date(date) > new Date()) || Number.POSITIVE_INFINITY,
        ).getTime(),
        series,
      }))
      .sort(({time: a}, {time: b}) => a - b)
      .find(({time}) => !!time)?.series;
  }

  ngOnDestroy() {
    this.collapseAnimation.destroy();
  }
}
