/* eslint-disable unicorn/no-useless-undefined */
/*
 * 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 {ChangeDetectionStrategy, Component, ElementRef, HostListener, Input} from '@angular/core';
import {SCDish, SCRatingRequest} from '@openstapps/core';
import {RatingProvider} from '../rating.provider';
import {ratingAnimation} from './rating.animation';
import {BehaviorSubject, filter, merge, mergeMap, of, ReplaySubject, withLatestFrom} from 'rxjs';
import {catchError, map} from 'rxjs/operators';

@Component({
  selector: 'stapps-rating',
  templateUrl: 'rating.html',
  styleUrls: ['rating.scss'],
  animations: [ratingAnimation],
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class StappsRatingComponent {
  performRating = new BehaviorSubject(false);

  userRating = new BehaviorSubject<number | undefined>(undefined);

  dish = new ReplaySubject<SCDish>(1);

  wasAlreadyRated = merge(
    this.dish.pipe(mergeMap(({uid}) => this.ratingProvider.hasRated(uid))),
    this.userRating.pipe(
      filter(it => it !== undefined),
      withLatestFrom(this.dish),
      mergeMap(([rating, {uid}]) => this.ratingProvider.rate(uid, rating as SCRatingRequest['rating'])),
      map(() => true),
      catchError(() => of(false)),
    ),
  );

  canBeRated = this.dish.pipe(mergeMap(dish => this.ratingProvider.canRate(dish)));

  @Input({required: true}) set item(value: SCDish) {
    this.dish.next(value);
  }

  constructor(
    readonly elementRef: ElementRef,
    readonly ratingProvider: RatingProvider,
  ) {}

  @HostListener('document:mousedown', ['$event'])
  clickOutside(event: MouseEvent) {
    if (this.userRating.value) return;
    if (!this.elementRef.nativeElement.contains(event.target)) {
      this.performRating.next(false);
    }
  }
}
