import {Component, ElementRef, EventEmitter, Input, OnChanges, OnDestroy, OnInit, Output, SecurityContext, ViewChild} from '@angular/core';

import {HttpClientModule} from '@angular/common/http';
import {HttpClient, HttpHeaders, HttpRequest, HttpEvent, HttpEventType, HttpResponse, HttpParams} from "@angular/common/http";

import {NzMessageService, UploadChangeParam, UploadFile, UploadFileStatus, UploadXHRArgs} from 'ng-zorro-antd';
import {DomSanitizer, SafeResourceUrl} from '@angular/platform-browser';
import cryptoJs from 'crypto-js';
import {v4} from 'uuid';

function httpHeadCall(requsetUrl, callback) {
  let xhr = new XMLHttpRequest();
  try {
    xhr.onreadystatechange = () => {
      try {
        if (xhr.readyState == 4) {
          if ((xhr.status >= 200 && xhr.status < 400)) {
            callback(true);
          } else {
            callback(false);
          }
        }
      } catch (e) {
        callback(false);
      }
    };
    xhr.open("HEAD", requsetUrl, true);
    xhr.send();
    xhr.timeout = 15000;
    xhr.onerror = (e) => {
      callback(false);
    };
    xhr.ontimeout = (e) => {
      callback(false);
    };
  } catch (e) {
    callback(false);
  }
}


@Component({
  selector: 'app-upload-video',
  templateUrl: './upload-video.component.html',
  styleUrls: ['./upload-video.component.scss']
})
export class UploadVideoComponent implements OnChanges, OnDestroy, OnInit {
  uploading = false;
  checking = false;
  checkVideoExists = false;
  uploadClicked = false;

  @Input()
  videoFile = null;
  uploaderInst = null;

  progress = 0;
  // @Input()
  // setCovering = false;

  @Input()
  videoUrl = '';
  @ViewChild('videoNode', {static: false }) videoNode: ElementRef;




  // @Input()
  // extractCoverFunc = null;

  @Output()
  videoIsAccessibleInCDN = new EventEmitter();

  @Output()
  videoUploaded = new EventEmitter();
  @Output()
  videoUploadFailure = new EventEmitter();
  @Output()
  onCapture = new EventEmitter();
  @Output()
  extractVideoCover = new EventEmitter();
  @Output()
  parentRef= new EventEmitter();

  @Input()
  showUploadBtn = true;
  @Input()
  showCapture = true;

  @Input()
  item: any;
  // videoItem = null;

  uploadUrl;
  uploadData;

  constructor(private nzMessageService: NzMessageService,
              private sanitization: DomSanitizer,
              private http:HttpClient
              // private cwService: _coursewareService,
              // private resService: ResourceService
              ) {
    this.uploading = false;
    this.videoFile = null;


    this.uploadUrl = (<any> window).courseware.uploadVideoUrl();
    this.uploadData = (<any> window).courseware.uploadData();

    

                
    window['air'].getUploadVideoCallback = (url, data) => {
      this.uploadUrl = url;
      this.uploadData = data;
    };

  }

  ngOnInit() {
    this.playVedioUrl = this.videoUrl.replace(`_h.mp4`, `_l.mp4`);;
    this.parentRef.emit(this);
  }


  md5Short(str, _salt) {
    return cryptoJs.MD5(str + _salt).toString();
  }
  ngOnChanges() {
    // if (!this.videoFile || this.showUploadBtn) {
    //   return;
    // }
    // this.beforeUpload(this.videoFile);
    // this.handleUpload();
  }
  ngOnDestroy(): void {
    URL.revokeObjectURL(this.videoUrl);
  }

  playVedioUrl = '';
  safeVideoUrl() {
    const url = this.videoUrl.replace(`_h.mp4`, `.mp4`).replace(`.mp4`, `_l.mp4`);
    console.log(`=============safeVideoUrl==============`,url);
    httpHeadCall(url, (flag)=>{
      if (flag) {
        this.playVedioUrl = url;
        this.videoIsAccessibleInCDN.emit(url);
      } else {
        setTimeout(() => {
          this.safeVideoUrl();
        }, 500);
      }
    });
    return this.playVedioUrl;
  }

  videoLoadedMetaData() {

  } 

  // fileToBlob(file) {
  //   let reader = new FileReader();
  //   reader.addEventListener('load', (e) => {
  //       let base64 = e.target.result;
  //       let blob = new Blob([base64], { type: file.type });
  //       console.log("Blob对象", blob);
  //   })
  //   reader.readAsDataURL(file)
  // } 


  
  customReq(item: UploadXHRArgs) {
    // md5值计算
    const protocolStr = document.location.protocol;
    const baseCDN = `${protocolStr}//teach.cdn.ireadabc.com`;
    const baseAPI = `${protocolStr}//openapi.iteachabc.com`;

    const fileName = v4().replace(/-/g, "");
    httpHeadCall(`${baseCDN}/${fileName}_h.mp4`, (flag)=>{
      if (flag) {
        item.onSuccess!({url: `${baseCDN}/${fileName}.mp4`}, item.file!, event);
      } else {
        this.http.get(`${baseAPI}/oss/timestamp`, {}).subscribe((tmps: string) => {
          const sign = cryptoJs.MD5(tmps+"iplayABC2019").toString();
          const params = new HttpParams().set('sign', sign).set('stmp', tmps);
          this.http.get(`${baseAPI}/oss/signature`, {params}).subscribe((res) => {
            const serve = res['data'];
            const formData = new FormData();
            formData.append('key', fileName+`.mp4`);
            formData.append('bucket', `iplayabc-worker-queue-videolmh`);
            formData.append('OSSAccessKeyId', serve.OSSAccessKeyId);
            formData.append('policy', serve.policy);
            formData.append('Signature', serve.signature);
            formData.append('success_action_status', '200');
            formData.append('file', item.file as any);
  
            //设置cors跨域请求
            const headerstemp = new HttpHeaders({  'Access-Control-Allow-Origin': '*' });
  
            item.action = `${protocolStr}//iplayabc-worker-queue-videolmh.oss-cn-beijing.aliyuncs.com`;
            const req = new HttpRequest('POST', item.action!, formData, {
              headers: headerstemp,
              reportProgress: true, //进度条
              // withCredentials: true
            });
            // Always returns a `Subscription` object. nz-upload would automatically unsubscribe it at correct time.
            return this.http.request(req).subscribe(
              (event: HttpEvent<{}>) => {
                if (event.type === HttpEventType.UploadProgress) {
                  if (event.total! > 0) {
                    // tslint:disable-next-line:no-any
                    (event as any).percent = (event.loaded / event.total!) * 100;
                  }
                  item.onProgress!(event, item.file!);
                } else if (event instanceof HttpResponse) {
                  item.onSuccess!({url: `${baseCDN}/${fileName}.mp4`}, item.file!, event);
                }
              },
              err => {
                console.log(err);
                item.onError!(err, item.file!);
              }
            );
          });
        });
      }
    });
  }; 

  handleChange(info: UploadChangeParam/* { type: string, file: UploadFile, event: any }*/): void {
    console.log(info);
    switch (info.type) {
      case 'start':
        if (!this.checkSelectFile(info.file)) {
          return;
        }
        this.uploading = true;
        this.progress = 0;
        break;
      case 'success':
        this.uploadSuccess(info.file);
        break;
      case 'progress':
        this.progress = info.event.percent;
        // this.doProgress(this.progress);
        break;
    }
  }

  captureVideo() {
    const video = this.videoNode.nativeElement;
    const cvs = document.createElement('canvas');
    const ctx = cvs.getContext("2d");
    cvs.width = video.videoWidth;
    cvs.height = video.videoHeight;
    ctx.drawImage(video, 0, 0, cvs.width, cvs.height);
    cvs.toBlob((blob)=>{
      this.onCapture.emit(blob)
    })
  }

  checkSelectFile(file) {
    if (!file.lastModified) {
      return false;
    }
    const delta = 5000;
    const isOverSize = (file.size / 1024 / 1024) < delta;
    if (!isOverSize) {
      this.nzMessageService.error(`video must smaller than ${delta}MB!`);
      return false;
    }
    return true;
  }
  checkHashFinish = (hash) => {
    this.checking = false;
    this.uploading = true;
  }

  uploadSuccess = (file) => {
    this.nzMessageService.info('Upload Success');
    // this.updateStatus(false);
    this.uploading = false;
    this.videoFile = null;
    // this.updateSource(url);
    this.videoUrl = file.response.url;
    this.videoUploaded.emit(file.response);
    setTimeout(() => {
      this.safeVideoUrl();
    }, 2000);
  }



  uploadFailure = (err, file) => {
    this.uploading = false;
    if (err.name && err.name === 'cancel') {
      return;
    }
    console.log(err);
    this.nzMessageService.error('Upload Error ' + err.message);
    this.videoUploadFailure.emit(file);
  }

  doProgress =  (p) => {
    if (p > 1) {
      p = 1;
    }
    if (p < 0) {
      p = 0;
    }
    // console.log(Math.floor(p * 100));
    this.progress =  Math.floor(p * 100);
  }
}

