import { Injectable, OnDestroy } from '@angular/core';
import { OAuthService } from 'angular-oauth2-oidc';
import { Subject , Subscription } from 'rxjs';
import { HttpClient } from "@angular/common/http";
import { UploadxService, UploadState,UploadxOptions} from 'ngx-uploadx';
import { AppConfig } from '../../shared/app.config';


@Injectable({ providedIn: 'root' })
export class ResumableFileUploadService implements OnDestroy{
  public files: Array<File> = new Array<File>();
  public isUploading = false;
  public totalProgress = 0;
  public isClosed = true;
  public isMinimized = false;
  public parentCode: string;
  public refresh: Subject<any> = new Subject<any>();
  public addedFiles: Subject<File> = new Subject<File>();
  private _eventSub:Subscription;
  private initialized = false;

  constructor(private httpClient: HttpClient,private oauthService: OAuthService,private uploadService: UploadxService,public appConfig: AppConfig) {
   
  }

  endPoint() {
    return `${this.appConfig.getConfig("apiEndPoint")}/api/v1/file`;
  }

  init() {
    if(!this.initialized) {
      this._eventSub=this.uploadService.init({
        endpoint:this.endPoint(),
        token:() => this.oauthService.getAccessToken(),
        chunkSize: 2097152}).subscribe((uploadState:UploadState) => {
        this.handleState(uploadState);  
     } );
     this.initialized=true;  
    }
  }

  updatetotalprogress() {
    let totalProgress =0;
    let n=0;
    for(let i =0;i<this.files.length;i++) {
      if(!this.files[i].error) {
        totalProgress+=this.files[i].progress;
        n++;
      }
    }
    this.totalProgress=totalProgress/this.files.length;
    if(this.totalProgress==100) this.isUploading=false;
  }

  handleState(state:UploadState) {
      const file =this.files.find((f) => f.identifier == state.uploadId )
      if(state.status != "cancelled" && !file) {
        const file = new File(state);
        this.files.push(file);
        this.isClosed=false;  
        this.addedFiles.next(file)
      }
      switch(state.status) {
        case "uploading": {         
          if(file) {
            this.isUploading = true;
            file.progress = (state.progress?state.progress:0);
          }
        }break;
        case "complete": {
            if(file) {
              const parts = state.url.split("/");
              file.itemCode = parts[parts.length-1];
              file.progress = (state.progress?state.progress:0);              
              file.success=true;
            }
        }break;
        case "error": {
          if(file) {
            file.error=true;
            file.errorMessage = state.response as string;
          }
        }break;
      }
      this.updatetotalprogress();
      this.refresh.next({});
  }

  addFiles = (files: any[], event: any, metadata:any) => {
    for (const f of files) {
      const options:UploadxOptions = {metadata:metadata};
      this.uploadService.handleFiles(f,options);
    }
  }
  
  toggleMinimize = function () {
    this.isMinimized = !this.isMinimized;
  };

  cancelFile = function (file) {
    this.uploadService.control({action:'cancel',uploadId:file.identifier});    
    const index = this.files.indexOf(file, 0);
    if (index > -1) {
      this.files.splice(index, 1);
    }
    if(this.files.length==0) {
      this.isUploading = false;
    }
  };

  doClose = function () {
    const toCancel = this.files.filter((f) => !f.success);
    toCancel.forEach(f => {
      this.uploadService.control({action:'cancel',uploadId:f.identifier});   
    });    
    this.files = new Array<File>();
    this.isClosed = true;
  }

  close = function () {
    let close = true;
    if (this.isUploading) {
      close = false;
    }
    if (close) {
      this.doClose();
    }
  }

  ngOnDestroy() {
    if(this._eventSub) this._eventSub.unsubscribe();
  }
}

export class File {
  private file: any;
  public fileName: string;
  public progress: number;
  public identifier: string;
  public itemCode: string;
  public success: boolean;
  public error: boolean;
  public errorMessage: string;


  constructor(state: UploadState) {
    this.file = state;
    this.fileName = state.file.name;
    this.progress = state.progress?state.progress:0;
    this.identifier = state.uploadId;
    this.success = false;
    this.error = false;
    this.errorMessage = "";
    this.itemCode = null;
  }
}
