import {
	Directive,
	EventEmitter,
	ElementRef,
	HostListener,
	Input,
	Output,
	OnInit,
} from '@angular/core';

import { FileUploader, FileUploaderOptions } from './file-uploader.class';

@Directive({ selector: '[ngxFileDrop]' })
export class FileDropDirective implements OnInit {
	@Input() public fullScreen: Boolean = true;
	@Input() public uploader: FileUploader;
	@Output() public fileOver: EventEmitter<any> = new EventEmitter();
	@Output() public onFileDrop: EventEmitter<File[]> = new EventEmitter<File[]>();

	protected element: ElementRef;

	public constructor(element: ElementRef) {
		this.element = element;
	}

	public getOptions(): FileUploaderOptions {
		return this.uploader.options;
	}

	public getFilters(): any {
		return {};
	}

	@HostListener('drop', ['$event'])
	public onDrop(event: any): void {
		const transfer = this._getTransfer(event);
		if (!transfer) {
			return;
		}

		const options = this.getOptions();
		const filters = this.getFilters();
		this._preventAndStop(event);
		this.uploader.addToQueue(transfer.files, options, filters);
		this.fileOver.emit(false);
		this.onFileDrop.emit(transfer.files);
	}

	@HostListener('dragover', ['$event'])
	public onDragOver(event: DragEvent): void {
		const transfer = this._getTransfer(event);
		if (!this._haveFiles(transfer.types)) {
			return;
		}

		transfer.dropEffect = 'copy';
		this._preventAndStop(event);
		this.fileOver.emit(true);
	}

	@HostListener('dragleave', ['$event'])
	public onDragLeave(event: DragEvent): any {
		if ((this as any).element) {
			if (event.currentTarget === (this as any).element[0]) {
				return;
			}
		}

		this._preventAndStop(event);
		this.fileOver.emit(false);
	}

	protected _getTransfer(event: any): any {
		return event.dataTransfer
			? event.dataTransfer
			: event.originalEvent.dataTransfer; // jQuery fix;
	}

	protected _preventAndStop(event: any): any {
		event.preventDefault();
		event.stopPropagation();
	}

	protected _haveFiles(types: any): any {
		if (!types) {
			return false;
		}

		if (types.indexOf) {
			return types.indexOf('Files') !== -1;
		} else if (types.contains) {
			return types.contains('Files');
		} else {
			return false;
		}
	}
	ngOnInit() {
		if (this.fullScreen) {
			if (typeof window !== 'undefined') {
				window.addEventListener(
					'dragenter',
					function (e: any) {
						e.preventDefault();
						this.fileOver.emit(true);
					}.bind(this),
				);
			}
		}
	}
}
