import {
  Directive,
  ElementRef,
  EventEmitter,
  HostListener,
  Output,
  Input,
  AfterViewInit
} from '@angular/core';

import { NGXLogger } from 'ngx-logger';
import { FileUploadQueueComponent } from '../components/file-upload-queue.component';
import {
  FileUploadItem,
  CommonApiService
} from '@ucap-webmessenger/api-common';
import { FileUtil } from '@ucap-webmessenger/core';
import { DialogService } from '../services/dialog.service';
import {
  AlertDialogComponent,
  AlertDialogResult,
  AlertDialogData
} from '../dialogs/alert.dialog.component';

@Directive({
  selector: 'input[ucapFileUploadFor], div[ucapFileUploadFor]'
})
export class FileUploadForDirective implements AfterViewInit {
  @Input()
  fileUploadQueue: FileUploadQueueComponent;

  @Output()
  public fileDragEnter = new EventEmitter<DataTransferItemList>();

  @Output()
  public fileDragOver = new EventEmitter<void>();

  @Output()
  public fileDragLeave = new EventEmitter<void>();

  @Output()
  public fileSelected = new EventEmitter<FileUploadItem[]>();

  dragOver = false;

  constructor(
    private commonApiService: CommonApiService,
    private elementRef: ElementRef,
    private logger: NGXLogger,
    private dialogService: DialogService
  ) {}

  ngAfterViewInit(): void {}

  @HostListener('window:dragenter', ['$event'])
  public onDragEnter(event: DragEvent): any {
    if (!this.isFileDrag(event.dataTransfer)) {
      return;
    }

    if (!this.dragOver) {
      this.fileDragEnter.emit(event.dataTransfer.items);
      this.dragOver = true;
      if (!!this.fileUploadQueue) {
        this.fileUploadQueue.onDragEnter(event.dataTransfer.items);
      }
    }
  }

  @HostListener('window:dragover', ['$event'])
  public onDragOver(event: DragEvent): any {
    if (!this.isFileDrag(event.dataTransfer)) {
      return;
    }

    // if (this.fileUploadQueue.isEventInElement(event)) {
    //   event.dataTransfer.dropEffect = 'copy';
    // } else {
    //   event.dataTransfer.dropEffect = 'none';
    // }
    event.preventDefault();
  }

  @HostListener('window:dragleave', ['$event'])
  public onDragLeave(event: DragEvent): any {
    if (!this.isFileDrag(event.dataTransfer)) {
      return;
    }

    if (event && event.pageX === 0 && event.pageY === 0) {
      this.fileDragLeave.emit();
      this.dragOver = false;
      if (!!this.fileUploadQueue) {
        this.fileUploadQueue.onDragLeave();
      }
    }
  }

  @HostListener('change')
  public onChange(): any {
    const files = this.elementRef.nativeElement.files;
    this.fileSelected.emit(FileUploadItem.fromFiles(files));
    this.elementRef.nativeElement.value = '';
  }

  @HostListener('window:drop', ['$event'])
  public onDrop(event: any): any {
    if (!this.isFileDrag(event.dataTransfer)) {
      return;
    }
    const files: FileList = event.dataTransfer.files;

    const checkExt = this.commonApiService.acceptableExtensionForFileTalk(
      FileUtil.getExtensions(files)
    );
    if (!checkExt.accept) {
      this.logger.debug('window:drop not acceptable');
      if (!!this.fileUploadQueue) {
        this.fileUploadQueue.onDragLeave();
      }
      this.elementRef.nativeElement.value = '';
      this.dragOver = false;

      this.dialogService.open<
        AlertDialogComponent,
        AlertDialogData,
        AlertDialogResult
      >(AlertDialogComponent, {
        data: {
          title: 'Alert',
          html: `지원하지 않는 파일형식입니다.${
            checkExt.reject.length > 0
              ? '<br/>(' + checkExt.reject.join(',') + ')'
              : ''
          }`
        }
      });

      return;
    }

    const fileUploadItems = FileUploadItem.fromFiles(files);
    this.fileSelected.emit(fileUploadItems);
    event.preventDefault();
    event.stopPropagation();
    this.elementRef.nativeElement.value = '';
    this.dragOver = false;
    if (!!this.fileUploadQueue) {
      this.fileUploadQueue.onDrop(fileUploadItems);
    }
  }

  private isFileDrag(dataTransfer: DataTransfer): boolean {
    if (0 >= dataTransfer.items.length) {
      return false;
    }

    // tslint:disable-next-line: prefer-for-of
    for (let i = 0; i < dataTransfer.items.length; i++) {
      const element = dataTransfer.items[i];
      if ('file' !== element.kind) {
        return false;
      }
    }

    return true;
  }
}
