import Event from 'ol/events/Event.js';
import Interaction from "ol/interaction/Interaction";
import EventType from 'ol/events/EventType';
import { TRUE } from 'ol/functions';
import { listen, unlistenByKey } from 'ol/events.js';



export class FileDragAndDropEvent extends Event {

    constructor(public file: File) {
        super('filedrop');
    }
}

/**
 * Dispatches events for dropped files
 */
export class FileDragAndDrop extends Interaction {

    private dropListenKeys_ = [];

    constructor() {
        super({
            handleEvent: TRUE,
        });

        this['target'] = null;
    }

    /**
     * @private
     */
    registerListeners_() {
        const map = this.getMap();
        if (map) {
            const dropArea = map.getViewport();
            this.dropListenKeys_ = [
                listen(dropArea, EventType.DROP, this.handleDrop, this),
                listen(dropArea, EventType.DRAGENTER, this.handleStop, this),
                listen(dropArea, EventType.DRAGOVER, this.handleStop, this),
                listen(dropArea, EventType.DROP, this.handleStop, this),
            ];
        }
    }

    /**
     * Activate or deactivate the interaction.
     * @param {boolean} active Active.
     * @observable
     * @api
     */
    setActive(active) {
        if (!this.getActive() && active) {
            this.registerListeners_();
        }
        if (this.getActive() && !active) {
            this.unregisterListeners_();
        }
        super.setActive(active);
    }

    /**
     * Remove the interaction from its current map and attach it to the new map.
     * Subclasses may set up event handlers to get notified about changes to
     * the map here.
     * @param {import("../PluggableMap.js").default} map Map.
     */
    setMap(map) {
        this.unregisterListeners_();
        super.setMap(map);
        if (this.getActive()) {
            this.registerListeners_();
        }
    }

    /**
     * @private
     */
    unregisterListeners_() {
        if (this.dropListenKeys_) {
            this.dropListenKeys_.forEach(unlistenByKey);
            this.dropListenKeys_ = null;
        }
    }

    /**
     * @param {DragEvent} event Event.
     */
    handleDrop(event): boolean {
        const files = event.dataTransfer.files;
        for (let i = 0, ii = files.length; i < ii; ++i) {
            const file = files.item(i);
            this.dispatchEvent(
                new FileDragAndDropEvent(
                    file,
                )
            );
        }
        return false;
    }

    /**
     * @param {DragEvent} event Event.
     */
    handleStop(event): boolean {
        event.stopPropagation();
        event.preventDefault();
        event.dataTransfer.dropEffect = 'copy';
        return false;
    }
}