import { Injectable, Inject, NgZone } from '@angular/core';
import {
  FileTalkDownloadRequest,
  CommonApiService
} from '@ucap-webmessenger/api-common';
import { map, take, finalize, catchError } from 'rxjs/operators';
import { MimeUtil, FileUtil } from '@ucap-webmessenger/core';
import { FileProtocolService } from '@ucap-webmessenger/protocol-file';
import { UCAP_NATIVE_SERVICE, NativeService } from '@ucap-webmessenger/native';
import {
  SnackBarService,
  AlertSnackbarComponent,
  AlertSnackbarData
} from '@ucap-webmessenger/ui';
import { TranslateService } from '@ngx-translate/core';
import { NGXLogger } from 'ngx-logger';
import { of } from 'rxjs';
import { HttpClient } from '@angular/common/http';

@Injectable({
  providedIn: 'root'
})
export class AppFileService {
  constructor(
    private commonApiService: CommonApiService,
    private fileProtocolService: FileProtocolService,
    @Inject(UCAP_NATIVE_SERVICE) private nativeService: NativeService,
    private snackBarService: SnackBarService,
    private translateService: TranslateService,
    private httpClient: HttpClient,
    private ngZone: NgZone,
    private logger: NGXLogger
  ) {}

  fileTalkDownlod(param: {
    req?: FileTalkDownloadRequest;
    directDownloadUrl?: string;
    fileName: string;
    fileDownloadUrl?: string;
    savePath?: string;
  }) {
    const req = param.req;
    const directDownloadUrl = param.directDownloadUrl;
    const fileName = param.fileName;
    const fileDownloadItem = req.fileDownloadItem;
    const fileDownloadUrl = param.fileDownloadUrl;
    const savePath = param.savePath;

    if (!!req && !!req.attachmentsSeq) {
      this.commonApiService
        .fileTalkDownload(req, fileDownloadUrl)
        .pipe(
          take(1),
          map(rawBlob => {
            const mimeType = MimeUtil.getMimeFromExtension(
              FileUtil.getExtension(fileName)
            );
            const blob = rawBlob.slice(0, rawBlob.size, mimeType);
            FileUtil.fromBlobToBuffer(blob)
              .then(buffer => {
                /** download check */
                this.fileProtocolService
                  .downCheck({
                    seq: req.attachmentsSeq
                  })
                  .pipe(take(1))
                  .subscribe();

                this.saveFile(buffer, fileName, mimeType, savePath);
              })
              .catch(reason => {
                this.fileTalkDownloadError(reason);
              });
          }),
          finalize(() => {
            if (!!fileDownloadItem) {
              setTimeout(() => {
                fileDownloadItem.downloadingProgress$ = undefined;
              }, 1000);
            }
          }),
          catchError(error => of(error))
        )
        .subscribe();
    } else if (!!directDownloadUrl) {
      this.commonApiService
        .fileDownload(directDownloadUrl, fileDownloadItem)
        .pipe(
          take(1),
          map(rawBlob => {
            const mimeType = MimeUtil.getMimeFromExtension(
              FileUtil.getExtension(fileName)
            );
            const blob = rawBlob.slice(0, rawBlob.size, mimeType);
            FileUtil.fromBlobToBuffer(blob)
              .then(buffer => {
                this.saveFile(buffer, fileName, mimeType, savePath);
              })
              .catch(reason => {
                this.fileTalkDownloadError(reason);
              });
          }),
          finalize(() => {
            if (!!fileDownloadItem) {
              setTimeout(() => {
                fileDownloadItem.downloadingProgress$ = undefined;
              }, 1000);
            }
          }),
          catchError(error => of(error))
        )
        .subscribe();
    }
  }

  private saveFile(
    buffer: Buffer,
    fileName: string,
    mimeType: string,
    savePath: string
  ): void {
    this.nativeService
      .saveFile(buffer, fileName, mimeType, savePath)
      .then(filePath => {
        if (!!filePath) {
          const snackBarRef = this.snackBarService.open(
            this.translateService.instant('common.file.results.savedToPath', {
              path: filePath
            }),
            this.translateService.instant('common.file.open'),
            {
              duration: 3000,
              verticalPosition: 'bottom',
              horizontalPosition: 'center'
            }
          );

          snackBarRef.onAction().subscribe(() => {
            snackBarRef.dismiss();
            this.ngZone.runOutsideAngular(() => {
              this.nativeService.openTargetItem(filePath).catch(reason => {
                this.logger.warn(reason);
              });
            });
          });
        } else {
          this.fileTalkDownloadError('fail');
        }
      })
      .catch(reason => {
        this.fileTalkDownloadError(reason);
      });
  }

  private fileTalkDownloadError(reason: any): void {
    this.logger.warn(reason);
    this.snackBarService.openFromComponent<
      AlertSnackbarComponent,
      AlertSnackbarData
    >(AlertSnackbarComponent, {
      data: {
        html: this.translateService.instant('common.file.errors.failToSave'),
        buttonText: this.translateService.instant('common.file.errors.label')
      }
    });
  }
}
