import { Component, Prop, Vue, Watch } from 'vue-property-decorator';
import S3UrlSignerFilesService from '@services/s3urlsigner/files';
import PrinterService from '@services/printer/index';
import includes from 'lodash/includes';
import { notifyError } from '@utils/notify';

@Component({})
export default class BasePreview extends Vue {
  @Prop({
    default: null,
    required: true,
  })
  extension: string | null;

  @Prop({
    default: '',
    required: true,
  })
  s3Url!: string;

  @Prop({
    default: false,
    required: false,
  })
  withoutTrigger: boolean;

  loading = false;
  dialog = false;
  supportedExtensions: string[] = [
    'xml',
    'xls',
    'xlsx',
    'ppt',
    'odt',
    'doc',
    'docx',
    'pdf',
    'jpg',
    'png',
    'tif',
  ];

  $refs!: {
    fileContainer: HTMLDivElement;
  };

  wrapFile(file: HTMLElement, container: Element): void {
    container.classList.add('PreviewDialog-Container');
    container.appendChild(file);
  }

  get supported(): boolean {
    if (!this.extension) return false;
    return includes(this.supportedExtensions, this.extension.toLowerCase());
  }

  get isOnline(): boolean {
    return navigator.onLine;
  }

  @Watch('s3Url', { immediate: true })
  public onFileChange(): void {
    if (this.withoutTrigger && this.s3Url) {
      this.dialog = true;
    }
  }

  async generatePreview(): Promise<void> {
    if (!this.extension) return;
    this.loading = true;
    try {
      const ref = this.$refs.fileContainer;
      const {
        file,
        presignedUrl,
      } = await S3UrlSignerFilesService.fetchFileFromS3ByUrl({
        url: this.s3Url,
      });
      switch (this.extension.toLowerCase()) {
        case 'pdf':
          // this.generatePDF(presignedUrl, ref);
          this.simplePrintPDF(file, ref);
          break;
        case 'jpg':
        case 'png':
        case 'tif':
          this.showImage(file, ref);
          break;
        case 'xls':
        case 'xlsx':
        case 'ppt':
        case 'odt':
        case 'doc':
        case 'docx':
          this.convertDocxToPdf(file, ref);
          break;
        case 'xml':
        default:
          this.showText(file, ref);
          break;
      }
    } catch (e) {
      if (e instanceof Error) notifyError(e.message);
      this.$emit('close');
    }
  }

  private async convertDocxToPdf(
    blob: Blob,
    container: Element
  ): Promise<void> {
    const urlIndex = 3;

    const template = new File([blob], this.s3Url.split('/')[urlIndex]);
    try {
      const data = await PrinterService.fetchConvertedFileSync({
        input: 'DOCX',
        output: 'PDF',
        template,
        parameters: JSON.stringify({ todo: 'allowEmptyParams' }),
        preventDownload: true,
      });
      const blob = data instanceof Blob ? data : new Blob([data]);
      const iframe = document.createElement('iframe');
      iframe.classList.add('PreviewDialog-Iframe');
      iframe.src = URL.createObjectURL(blob);

      container.appendChild(iframe);
      this.loading = false;
    } catch {
      throw new Error(
        '[components][common][base-review][index][PrinterService]'
      );
    }
  }

  // заменил работу с pdf, если все будет работать норм можно будет либу выпилить
  private simplePrintPDF(file: Blob, container: Element): void {
    const blob = new Blob([file], { type: 'application/pdf' });
    const iframe = document.createElement('iframe');
    iframe.classList.add('PreviewDialog-Iframe');
    iframe.src = URL.createObjectURL(blob);
    container.appendChild(iframe);
    this.loading = false;
  }

  showImage(file: Blob, container: Element): void {
    const image = new File([file], `img.${this.extension}`);
    const url = URL.createObjectURL(image);
    const img = document.createElement('img');
    img.src = url;
    img.classList.add('PreviewDialog-Img');
    this.wrapFile(img, container);
    this.loading = false;
  }

  async showText(file: Blob, container: Element): Promise<void> {
    // Используется вместо Blob.text(), для совместимости c Yandex Browser
    // и Mozilla Firefox for ALT Linux v.68.9.0 и выше.
    const text = await new Response(file).text();
    const pre = document.createElement('pre');
    pre.innerText = text;
    pre.classList.add('PreviewDialog-Pre', 'xml');
    this.wrapFile(pre, container);
    this.loading = false;
  }

  clickHandler(): void {
    this.dialog = true;
  }

  clearModel(): void {
    this.loading = false;
    this.dialog = false;
    this.$refs.fileContainer?.firstChild &&
      this.$refs.fileContainer.removeChild(this.$refs.fileContainer.firstChild);
    this.$emit('close');
  }

  destroyed(): void {
    this.clearModel();
  }
}
