import { Component, ChangeDetectionStrategy, Input, inject } from '@angular/core';
import { CommonData, CommonService, ScreenItem } from '../services/common.service';
import { MessageService } from '../services/message.service';
import { Router } from '@angular/router';
import { BehaviorSubject, Subject, Observable } from 'rxjs';
import { catchError, map, tap, switchMap, filter } from 'rxjs/operators';
import { DragEndEvent, KENDO_SORTABLE } from '@progress/kendo-angular-sortable';
import * as util from '../utils/util';
import { AsyncPipe } from '@angular/common';
import { ActiveClassDirective } from '../directives/active-class-directive';
import { HoverClassDirective } from '../directives/hover-class-directive';
import { FastButtonComponent } from "../elements/fast-button.component";
import { FastTipDirective } from '../elements/fast-tip.directive';
import { FastSpinnerComponent } from "../elements/fast-spinner.component";
import { toObservable } from '@angular/core/rxjs-interop';
import { FastSVGComponent } from '../elements/fast-svg.component';

@Component({
  selector: 'global-favorites[isOverlay]',
  changeDetection: ChangeDetectionStrategy.OnPush,
  styles: `
    @reference "../../../styles/site.css";
    :host {
      @apply absolute w-75 h-full top-10 right-0 z-8881;
    }
  `,
  templateUrl: './global-favorites.component.html',
  imports: [AsyncPipe, KENDO_SORTABLE, ActiveClassDirective, HoverClassDirective, FastButtonComponent, FastTipDirective, FastSpinnerComponent, FastSVGComponent]
})
export class GlobalFavoritesComponent {
  @Input() isOverlay: boolean = true;

  commonService = inject(CommonService);
  messageService = inject(MessageService);
  router = inject(Router);

  favorites$: Observable<CommonData>
  saveFavorites$ = new Subject()
  addFavorite$ = new Subject<string>()
  favoritesLoading$ = new BehaviorSubject<boolean>(true)
  saveFavoritesResult$: Observable<void>
  addFavoriteResult$: Observable<void>

  localFavorites: ScreenItem[] = [];
  isFavoriteDragging: boolean = false;

  constructor() {
    this.favorites$ = toObservable(this.commonService.commonDataRes.value).pipe(
      filter(data => data != null),
      tap(data => {
        this.localFavorites = data.favorites;
        this.favoritesLoading$.next(false);
      })
    )

    this.saveFavoritesResult$ = this.saveFavorites$.pipe(
      switchMap(() => {
        this.favoritesLoading$.next(true);
        return this.commonService.saveFavorites(this.localFavorites);
      }),
      map(() => {
        this.favoritesLoading$.next(false);
      }),
      catchError(err => {
        this.favoritesLoading$.next(false);
        return util.handleError(err, this.messageService)
      })
    )

    this.addFavoriteResult$ = this.addFavorite$.pipe(
      switchMap(url => {
        this.favoritesLoading$.next(true);
        url = url || window.location.href;
        return this.commonService.addFavorite(url);
      }),
      map(result => {
        if (result) {
          this.localFavorites.push(result);
          this.localFavorites = [...this.localFavorites];
        }
        this.favoritesLoading$.next(false);
      }),
      catchError(err => {
        this.favoritesLoading$.next(false);
        return util.handleError(err, this.messageService)
      })
    )
  }

  addFavorite(url: string = null) {
    this.addFavorite$.next(url);
  }

  removeFavorite(favoriteId: number) {
    this.localFavorites = this.localFavorites.filter(x => x.id !== favoriteId);
    this.saveFavorites$.next(null);
  }

  favoriteClick(screenItem: ScreenItem) {
    if (!this.isFavoriteDragging)
      this.externalNavigate(screenItem.path);
  }

  favoriteDragStart() {
    this.isFavoriteDragging = true;
  }

  favoriteDragEnd(event: DragEndEvent) {
    if (event.index === event.oldIndex)
      //if dragged to same position then immediately set dragging to false so that tiny movements still trigger a navigation
      this.isFavoriteDragging = false;
    else {
      //if dragged to new position then delay setting dragging to false since we don't want actual drags to navigate to a new url
      setTimeout(() => this.isFavoriteDragging = false);
      this.saveFavorites$.next(null);
    }
  }

  externalNavigate(path: string) {
    this.router.navigate(['/externalRedirect', { externalUrl: path }], {
      skipLocationChange: true,
    });
  }
}
