import { HttpErrorResponse } from '@angular/common/http';
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core';
import { Printer, DomainPrinterService } from '@domain/printer';
import { UiModalRef } from '@ui/modal';
import { isResponseArgs } from '@utils/object';
import { Observable, Subscription } from 'rxjs';
import { map, shareReplay } from 'rxjs/operators';
import { PrintModalData } from './modal-printer.data';

@Component({
  selector: 'modal-print-cart',
  templateUrl: 'modal-printer.component.html',
  styleUrls: ['modal-printer.component.scss'],
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class PrintModalComponent implements OnInit, OnDestroy {
  selectedPrinterKey: string;
  printers$: Observable<Printer[]>;

  error = false;
  errorMessage = 'Der Druckauftrag konnte nicht ausgeführt werden.';
  loaded = false;

  private subscriptions = new Subscription();

  constructor(
    protected printerService: DomainPrinterService,
    public modalRef: UiModalRef<string, PrintModalData>,
    private cdr: ChangeDetectorRef
  ) {}

  ngOnInit() {
    this.initPrinters();
  }

  ngOnDestroy() {
    this.subscriptions?.unsubscribe();
  }

  initPrinters() {
    let printerResult$: Observable<Printer[] | { error: string }>;

    if (this.modalRef.data.printerType === 'Office') {
      printerResult$ = this.printerService.getAvailableOfficePrinters();
    } else if (this.modalRef.data.printerType === 'Label') {
      printerResult$ = this.printerService.getAvailableLabelPrinters();
    } else {
      printerResult$ = this.printerService.getAvailablePrinters();
    }

    this.printers$ = printerResult$.pipe(
      map((printers) => {
        this.loaded = true;
        if (Array.isArray(printers)) {
          return printers;
        } else {
          this.setError(printers.error);
          return [];
        }
      }),
      shareReplay()
    );

    this.subscriptions.add(
      this.printers$.subscribe((printers) => {
        const defaultPrinter = printers.find((p) => p.selected);
        this.selectedPrinterKey = defaultPrinter?.key || printers[0]?.key;
        if (!!defaultPrinter) {
          if (!!this.modalRef?.data?.printImmediately) {
            this.print();
          }
        }
        this.cdr.markForCheck();
      })
    );
  }

  setError(errorMessage?: string) {
    this.error = true;
    if (!!errorMessage) {
      this.errorMessage = errorMessage;
    }
  }

  async print() {
    this.loaded = false;
    try {
      const printResponse = await this.modalRef.data.print(this.selectedPrinterKey);
      if (!printResponse.error) {
        this.modalRef.close();
      } else {
        this.setError(printResponse.message);
      }
    } catch (error) {
      if (error instanceof HttpErrorResponse) {
        if (isResponseArgs(error.error)) {
          this.setError(error.error.message);
        } else {
          this.setError(error.message);
        }
      }
    }

    this.loaded = true;
    this.cdr.markForCheck();
  }
}
