import {Component, EventEmitter, OnInit, Output} from '@angular/core';
import {FileInfo, FileRestrictions, SuccessEvent, UploadEvent, UploadProgressEvent} from '@progress/kendo-angular-upload';
import {AuthService} from '../service/auth.service';
import {debounce} from 'ts-debounce';
import {Router} from '@angular/router';
import {PageChangeEvent} from '@progress/kendo-angular-pager';
import {UploadAttachService} from '../service/upload.attach.service';
import {AppConfig} from '../app.config';
import {UploadMetalList, UploadMetaModel} from '../models/uploadMetaModel';
import {UploadingInfoModel} from '../models/uploading.info.model';

class UploadingCards{
  Uploading = false;
  IsDuplicate = false;
  IsNew = false;
  Info: UploadingInfoModel = new UploadingInfoModel({});
  Meta: UploadMetaModel = new UploadMetaModel({});
}

@Component({
  selector: 'app-lender-uploads',
  templateUrl: './lender-uploads.component.html',
  styleUrls: ['./lender-uploads.component.scss'],
})
export class LenderUploadsComponent implements OnInit {
  @Output() uploadSuccessful: EventEmitter<SuccessEvent> = new EventEmitter<SuccessEvent>();
  @Output() uploadClick: EventEmitter<FileInfo> = new EventEmitter<FileInfo>();
  @Output() uploadComplete: EventEmitter<FileInfo> = new EventEmitter<FileInfo>();
  @Output() upload: EventEmitter<boolean> = new EventEmitter<boolean>();


  public loading = false;

  uploadSaveUrl = ''; // should represent an actual API endpoint
  uploadRemoveUrl =  ''; // should represent an actual API endpoint

  public allUploads: UploadingCards[]  = [];


  public skip = 0;
  public pageSize = 12;
  public total = 0;
  public strFilter = '';

  private debouncedSearch: any;

  myRestrictions: FileRestrictions = {
    allowedExtensions: ['.pdf', '.xls', '.xlsx'],
    maxFileSize: 30240000,
    minFileSize: 1000,
  };

  constructor(private auth: AuthService, private router: Router, private uas: UploadAttachService, private config: AppConfig) {
    this.uploadSaveUrl = this.config.apiUrl + 'lender-upload/';
    this.uploadRemoveUrl = this.config.apiUrl + 'lender-upload-remove/';
  }


  ngOnInit(): void {
    this.debouncedSearch = debounce(this.loadDisplayRecords, 500);
    this.uploadSaveUrl = this.auth.getUrl('lender-upload/');
    this.uploadRemoveUrl = this.auth.getUrl('lender-upload-remove/');
    this.loadAllUploads();
  }

  public onClick( files: any): void{
    this.uploadClick.emit(files[0]);
  }

  public onSuccess(ss: SuccessEvent ): void {
    this.uploadSuccessful.emit(ss);

    const idx = this.uid2Idx(ss.files[0].uid);
    this.allUploads[idx].Meta = new UploadMetaModel(ss.response.body);
    this.allUploads[idx].Info.MetaId = this.allUploads[idx].Meta.Id; // trigger analysis
    this.allUploads[idx].IsDuplicate = ss.response.body.IsDuplicate;

    // remove card
    const uid = ss.files[0].uid;
    if (this.allUploads[idx].IsDuplicate ) {
      this.allUploads[idx].Info.Progress = 100;
      const timer = setInterval(() => {
        this.allUploads[idx].Info.Progress -= this.randBetween(1, 10);  // when many cards to be removed, it's better not altogether
        if (this.allUploads[idx].Info.Progress <= 0 ) {
          clearInterval(timer);
          this.allUploads = this.allUploads.filter(v => {
            return v.Info.UniqueId !== uid;
          });
        }
      }, 100);
    }
  }

  private randBetween(start: number, end: number): number {
    return Math.floor(Math.random() * end) + start;
  }

  private uid2Idx(uid: string): number {
    return this.allUploads.findIndex( v => {
      return v.Info.UniqueId === uid;
    });
  }

  public onStartUpload(ss: UploadEvent ): void {
    const uc = new UploadingCards();
    uc.Uploading = true;
    uc.IsDuplicate = false;
    uc.IsNew = true;
    uc.Info.UniqueId = ss.files[0].uid;
    uc.Info.FileName = ss.files[0].name;
    uc.Info.Progress = 0;
    uc.Info.MetaId = 0 ;
    this.allUploads.unshift(uc);

  }

  public onComplete(): void {
    console.log('ok completed');
  }

  public onUploadError(e: any): void {
    console.log(e);
  }

  public uploadProgress(prog: UploadProgressEvent): void {
    prog.files.forEach( v => {
      const idx = this.uid2Idx(v.uid);
      this.allUploads[idx].Info.Progress = prog.percentComplete.valueOf();
      // console.log(prog.percentComplete.valueOf(), v.uid, v);
    } );
  }

  public show( i: number): void{
    this.router.navigate(['/upload-details/' + i]);
  }


  public onPageChange(e: PageChangeEvent): void {
    this.skip = e.skip;
    this.pageSize = e.take;
    this.loadDisplayRecords();
  }

  private loadAllUploads(): void{
    this.skip = 0;
    this.onFilterUploads(this.strFilter);
  }

  public onFilterUploads(hint: string): void {
    this.skip = 0;
    this.strFilter = hint;
    this.debouncedSearch();
  }

  private loadDisplayRecords(): void {
    this.allUploads = [];
    this.loading = true;
    this.uas.getUploadMetaList(this.skip, this.pageSize, this.strFilter).subscribe(
      (resp: UploadMetalList ) => {
        this.loading = false;
        this.total = resp.Total;
        resp.Data.forEach((v) => {
          const uc = new UploadingCards();
          uc.Uploading = false;
          uc.Meta = new UploadMetaModel(v);
          this.allUploads.push(uc);
        });
      }, err => { this.loading = false; },
      () => { this.loading = false; }
    );
  }

  public onDelete(ulMeta: UploadMetaModel): void{
    this.allUploads = this.allUploads.filter((v) => {
      return v.Meta.Id !== ulMeta.Id;
    });
    // console.log('delete', ulMeta, this);
  }

  public onCompleteSingle(uid: string): void {
    const idx = this.uid2Idx(uid);
    if (this.allUploads[idx] !== undefined ){
      this.allUploads[idx].Uploading = false;
    }
  }
}
