import { Component, OnInit, Output, EventEmitter, OnDestroy, ViewChild, ChangeDetectorRef } from '@angular/core';
import { PrinterService } from '../../core/services/printer.service';
import { ModalService, ButtonComponent } from '@libs/ui';
import { Subject } from 'rxjs';
import { takeUntil, map, tap, delay } from 'rxjs/operators';
import { Printer } from '../../core/models/printer.model';
import { PRINT_ERROR_MSG } from './printer-selection.constants';

@Component({
  selector: 'app-printer-selection',
  templateUrl: './printer-selection.component.html',
  styleUrls: ['./printer-selection.component.scss'],
})
export class PrinterSelectionComponent implements OnInit, OnDestroy {
  id = 'printer-modal';
  options: string[] | number[];
  selected: string | number;
  selectedPrinterValue: string;
  printers: { key: string; text: string; selected: boolean }[] = [];
  destroy$ = new Subject();
  error = false;
  errorMessage = PRINT_ERROR_MSG;
  loaded = false;
  printingRequested = false;
  submited = false;
  @Output() print: EventEmitter<string> = new EventEmitter();
  @Output() closed = new EventEmitter();
  @ViewChild('printBtn') printBtn: ButtonComponent;

  constructor(private printerService: PrinterService, private modalService: ModalService, private cdr: ChangeDetectorRef) {}

  ngOnInit() {}

  printerSelected(value: string | number) {
    this.selected = value;
    this.selectedPrinterValue = this.printers.find((t) => t.text === this.selected).key;
  }

  emitPrint() {
    if (this.loaded) {
      this.print.emit(this.selectedPrinterValue);
      this.printBtn.startLoading();
    } else {
      this.printingRequested = true;
      this.printBtn.startLoading();
    }
  }

  loadPrinters() {
    this.loaded = false;
    this.error = false;
    this.printerService
      .getAvailablePrinters()
      .pipe(takeUntil(this.destroy$))
      .subscribe((response) => {
        if ((response as { error: string }).error) {
          const errorResponse = response as { error: string };
          this.error = true;
          this.errorMessage = errorResponse.error;
          return;
        }
        const result = response as Printer[];
        this.printers = result.map((t) => {
          return { key: t.key, text: t.description, selected: t.selected };
        });
        const selectedPrinter = this.printers.find((printer) => printer.selected);
        this.options = this.printers.map((t) => t.text);
        this.selectedPrinterValue = selectedPrinter ? selectedPrinter.key : this.printers[0].key;
        this.selected = selectedPrinter ? selectedPrinter.text : this.options[0];
        this.error = false;
        this.loaded = true;
        if (this.printBtn) {
          this.printBtn.stopLoading();
        }
        if (!this.selected) {
          this.error = true;
          this.errorMessage = 'No available printers';
        }
        this.cdr.markForCheck();
      });
  }

  openDialog() {
    this.loadPrinters();
    this.modalService.open(this.id);
  }

  closeModal() {
    this.modalService.close(this.id);
    if (this.printBtn) {
      this.printBtn.stopLoading();
    }
    this.closed.emit();
  }

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

  ngOnDestroy() {
    if (this.printBtn) {
      this.printBtn.stopLoading();
    }
    this.destroy$.next();
  }

  contentLoaded() {
    if (this.printingRequested) {
      this.print.emit(this.selectedPrinterValue);
    }
  }
}
