import { Clipboard } from '@angular/cdk/clipboard';
import { DatePipe } from '@angular/common';
import { Component, ChangeDetectionStrategy, Input, OnChanges, SimpleChanges, Optional, HostBinding } from '@angular/core';
import { DomainTaskCalendarService } from '@domain/task-calendar';
import { FileDTO } from '@swagger/checkout';
import { DisplayInfoDTO } from '@swagger/eis';
import { DateAdapter } from '@ui/common';
import { UiModalRef, UiModalService } from '@ui/modal';
import { isNullOrUndefined } from '@utils/common';
import { combineLatest, ReplaySubject, Subject } from 'rxjs';
import { catchError, filter, first, map, shareReplay, startWith, switchMap } from 'rxjs/operators';
import { ArticleListModalComponent } from '../../modals/article-list/article-list-modal.component';
import { ImageViewerModalComponent } from '../../modals/image-viewer/image-viewer-modal.component';
import { ImageViewerModalData } from '../../modals/image-viewer/image-viewer-modal.data';
import { PdfViewerModalComponent } from '../../modals/pdf-viewer/pdf-viewer-modal.component';
import { PdfViewerModalData } from '../../modals/pdf-viewer/pdf-viewer-modal.data';
import { WebViewerModalComponent } from '../../modals/web-viewer/web-viewer-modal.component';

@Component({
  selector: 'page-task-info',
  templateUrl: 'task-info.component.html',
  styleUrls: ['task-info.component.scss'],
  changeDetection: ChangeDetectionStrategy.OnPush,
  providers: [DatePipe],
})
export class TaskInfoComponent implements OnChanges {
  @Input()
  info: DisplayInfoDTO;

  @Input()
  showTaskDate: boolean;

  get dayOfWeek() {
    if (this.checkSameDay()) {
      return 'Heute';
    }
    return this.datePipe.transform(this.date, 'EEEE');
  }

  get date(): Date {
    const taskDate = this.info.taskDate;
    const publicationDate = this.info.publicationDate;
    const announcementDate = this.info.announcementDate;
    return this.domainTaskCalendarService.getDisplayInfoDate({ taskDate, publicationDate, announcementDate });
  }

  get timeSpan(): string {
    if (this.info?.timeFrom && this.info?.timeTo) {
      const dateFrom = new Date(this.info?.timeFrom);
      const dateTo = new Date(this.info?.timeTo);
      return `${this.datePipe.transform(dateFrom, 'HH:mm')} - ${this.datePipe.transform(dateTo, 'HH:mm')}`;
    }
    return 'Ganztägig';
  }

  get taskDate(): string {
    if (this.info?.taskDate && this.info?.taskOverdueDate) {
      const dateFrom = new Date(this.info?.taskDate);
      const dateTo = new Date(this.info?.taskOverdueDate);
      if (dateTo.getHours() === 0 && dateTo.getMinutes() === 0) {
        dateTo.setSeconds(dateTo.getSeconds() - 1);
      }

      if (dateFrom.getHours() === dateTo.getHours() && dateFrom.getMinutes() === dateTo.getMinutes()) {
        if (this.dateAdapter.equals({ first: dateFrom, second: dateTo, precision: 'day' })) {
          return `am ${this.datePipe.transform(dateFrom, 'dd.MM.yy')}`;
        }
        return `${this.datePipe.transform(dateFrom, 'dd.MM.yy')} bis ${this.datePipe.transform(dateTo, 'dd.MM.yy')}`;
      }

      return `${this.datePipe.transform(dateFrom, 'dd.MM.yy')} bis ${this.datePipe.transform(dateTo, 'dd.MM.yy')}`;
    }
  }

  get noteValue() {
    return sessionStorage.getItem(`INFO_NOTE_${this.info?.id}`) || '';
  }

  private info$ = new ReplaySubject<DisplayInfoDTO>();

  showVlbtixIcon$ = this.info$.pipe(map((info) => (info?.link ? new URL(info.link).hostname === 'www.vlbtix.de' : false)));

  teaser$ = this.info$.pipe(
    filter((info) => !isNullOrUndefined(info)),
    switchMap((info) => this.domainTaskCalendarService.getTeaserFile({ infoId: info.id }).pipe(catchError((error) => [undefined])))
  );

  attachments$ = this.info$.pipe(
    filter((info) => info.attachments > 0),
    switchMap((info) => this.domainTaskCalendarService.getFiles({ infoId: info.id })),
    map((response) => response.result)
  );

  type$ = this.info$.pipe(map((info) => this.domainTaskCalendarService.getInfoType(info)));

  showNotes$ = this.type$.pipe(map((type) => type === 'Info' || type === 'Task'));

  indicatorColor$ = this.info$.pipe(map((info) => this.domainTaskCalendarService.getProcessingStatusColorCode(info)));

  private noteAdded$ = new Subject();

  notes$ = combineLatest([this.info$, this.noteAdded$.pipe(startWith([undefined]))]).pipe(
    switchMap(([info]) => this.domainTaskCalendarService.getComments({ infoId: info.id })),
    map((res) =>
      res.result.map((comment) => ({
        date: new Date(comment.created),
        note: comment.text,
      }))
    )
  );

  processingStatus$ = this.info$.pipe(
    map((info) => this.domainTaskCalendarService.getProcessingStatusList(info)),
    shareReplay()
  );

  showUpdateComment$ = combineLatest([this.info$, this.processingStatus$]).pipe(
    map(
      ([info, processingStatus]) => !!info.updateComment && ((info.successor && processingStatus.includes('Removed')) || info.predecessor)
    )
  );

  @HostBinding('class')
  get statusClass() {
    return this.domainTaskCalendarService.getProcessingStatusList(this.info);
  }

  constructor(
    private dateAdapter: DateAdapter,
    private datePipe: DatePipe,
    private domainTaskCalendarService: DomainTaskCalendarService,
    private uiModal: UiModalService,
    private clipboard: Clipboard,
    @Optional() private modalRef: UiModalRef
  ) {}

  ngOnChanges({ info }: SimpleChanges): void {
    if (info) {
      this.info$.next(this.info);
    }
  }

  setNoteValue(note: string) {
    sessionStorage.setItem(`INFO_NOTE_${this.info?.id}`, note);
  }

  async openFile(file: FileDTO) {
    const content = await this.domainTaskCalendarService.getFile({ fileId: file.id }).toPromise();

    // TODO: Logik um den richtigen Dialog zu öffnen
    if (file.mime === 'application/pdf') {
      this.uiModal.open({
        content: PdfViewerModalComponent,
        title: file?.name,
        config: { showScrollbarX: true, showScrollbarY: false },
        data: {
          file,
          content,
        } as PdfViewerModalData,
      });
    } else if (['image/gif', 'image/jpeg', 'image/png', 'image/svg+xml'].includes(file.mime)) {
      this.openImage(file, content);
    }
  }

  openImage(file: FileDTO, content: Blob) {
    this.uiModal.open({
      content: ImageViewerModalComponent,
      title: file?.name,
      data: {
        file,
        content,
      } as ImageViewerModalData,
    });
  }

  copyArticleList() {
    const eanString = this.info.articles.map((article) => article.data.ean).join(';');
    this.clipboard.copy(eanString);
  }

  checkSameDay(): boolean {
    return this.dateAdapter.equals({ first: this.date, second: this.dateAdapter.today(), precision: 'day' });
  }

  async openArticleList() {
    const articleListModal = this.uiModal.open({
      content: ArticleListModalComponent,
      data: this.info,
    });
    const result = await articleListModal.afterClosed$.pipe(first()).toPromise();
    if (result.data === 'closeAll') {
      this.modalRef?.close();
    }
  }

  openUrl(url: string) {
    this.uiModal.open({
      content: WebViewerModalComponent,
      title: 'Digitale Titelvorschau',
      data: url,
      config: {
        width: '1120px',
        showScrollbarY: false,
      },
    });
  }

  async addNote(note: string) {
    await this.domainTaskCalendarService.addComment({ infoId: this.info.id, text: note }).toPromise();
    sessionStorage.removeItem(`INFO_NOTE_${this.info?.id}`);
    this.noteAdded$.next();
  }
}
