/*
 * 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 {ChangeDetectorRef, Component, EventEmitter, Input, OnInit, Output} from '@angular/core';
import {ModalController} from '@ionic/angular/standalone';
import {SCDateSeries} from '@openstapps/core';
import {
  DateSeriesRelevantData,
  ScheduleProvider,
  toDateSeriesRelevantData,
} from '../../calendar/schedule.provider';
import {CalendarService} from '../../calendar/calendar.service';
import {
  groupBy,
  groupByProperty,
  mapValues,
  stringSortBy,
  uniqBy,
  differenceBy,
} from '@openstapps/collection-utils';
import {SelectionValue, TreeNode} from './tree-node';

/**
 * Shows a horizontal list of action chips
 */
@Component({
  selector: 'stapps-edit-event-selection',
  templateUrl: 'edit-event-selection.html',
  styleUrls: ['edit-event-selection.scss'],
})
export class EditEventSelectionComponent implements OnInit {
  /**
   * The item the action belongs to
   */
  @Input() items: SCDateSeries[];

  /**
   * Selection of the item
   */
  selection: TreeNode<TreeNode<SelectionValue>>;

  /**
   * Uuids
   */
  partialDateSeries: DateSeriesRelevantData[];

  @Output()
  modified = new EventEmitter();

  constructor(
    readonly ref: ChangeDetectorRef,
    readonly scheduleProvider: ScheduleProvider,
    readonly calendar: CalendarService,
    readonly modalController: ModalController,
  ) {}

  ngOnInit() {
    this.partialDateSeries = this.scheduleProvider.partialEvents$.value;
    this.reset();
  }

  private getSelection(): {
    selected: DateSeriesRelevantData[];
    unselected: DateSeriesRelevantData[];
  } {
    const selection = mapValues(
      groupByProperty(
        this.selection.children.flatMap(it => it.children),
        'selected',
      ),
      value => value.map(it => toDateSeriesRelevantData(it.item)),
    );

    return {selected: selection.true ?? [], unselected: selection.false ?? []};
  }

  getModifiedEvents(): DateSeriesRelevantData[] {
    const {selected, unselected} = this.getSelection();

    return uniqBy(
      [...differenceBy(this.partialDateSeries, unselected, it => it.uid), ...selected],
      it => it.uid,
    );
  }

  reset() {
    this.selection = new TreeNode(
      Object.values(
        groupBy(
          this.items
            .map(item => ({
              selected: this.partialDateSeries.some(it => it.uid === item.uid),
              item: item,
            }))
            .sort(stringSortBy(it => it.item.repeatFrequency)),
          it => it.item.repeatFrequency,
        ),
      ).map(item => new TreeNode(item, this.ref)),
      this.ref,
    );
  }

  /**
   * Save selection
   */
  save() {
    this.scheduleProvider.partialEvents$.next(this.getModifiedEvents());
  }
}
