import { __esDecorate, __runInitializers } from "tslib";
/* eslint-disable @typescript-eslint/no-explicit-any */
/* eslint-disable @typescript-eslint/no-unused-vars */
import { html } from 'lit';
import { property } from 'lit/decorators.js';
import '../md/icons/ui-icon.js';
export const dragEnterHandler = Symbol('dragEnterHandler');
export const dragLeaveHandler = Symbol('dragLeaveHandler');
export const dragOverHandler = Symbol('dragOverHandler');
export const dropHandler = Symbol('dropHandler');
/**
 * Adds methods to accept files via drag and drop.
 * The mixin register the dnd events on the body element. When an object is dragged over the window it adds
 * this `drop-target` class to the `body` element. Additionally it sets the `dropTargetActive` property.
 *
 * The mixin also assumes that when the `drop-target` is set then the `drop-info` overlay is rendered.
 * However, it does not change the logic if the element is not in the DOM.
 * Use the provided `dropTargetTemplate()` function to generate template for the drag info.
 *
 * The class implementing this mixin should override the `processDroppedFiles(files)`  method
 * to process the incoming files.
 *
 * @mixin
 */
export const FileDropMixin = (superClass) => {
    let MyMixinClass = (() => {
        let _classSuper = superClass;
        let _dropTargetActive_decorators;
        let _dropTargetActive_initializers = [];
        let _dropTargetActive_extraInitializers = [];
        return class MyMixinClass extends _classSuper {
            static {
                const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
                __esDecorate(this, null, _dropTargetActive_decorators, { kind: "accessor", name: "dropTargetActive", static: false, private: false, access: { has: obj => "dropTargetActive" in obj, get: obj => obj.dropTargetActive, set: (obj, value) => { obj.dropTargetActive = value; } }, metadata: _metadata }, _dropTargetActive_initializers, _dropTargetActive_extraInitializers);
                if (_metadata) Object.defineProperty(this, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
            }
            #dropTargetActive_accessor_storage = __runInitializers(this, _dropTargetActive_initializers, void 0);
            get dropTargetActive() { return this.#dropTargetActive_accessor_storage; }
            set dropTargetActive(value) { this.#dropTargetActive_accessor_storage = value; }
            dropTarget = (__runInitializers(this, _dropTargetActive_extraInitializers), document.body);
            constructor(...args) {
                super(...args);
                this[dragEnterHandler] = this[dragEnterHandler].bind(this);
                this[dragLeaveHandler] = this[dragLeaveHandler].bind(this);
                this[dragOverHandler] = this[dragOverHandler].bind(this);
                this[dropHandler] = this[dropHandler].bind(this);
                this.dropTargetActive = false;
            }
            connectedCallback() {
                const { dropTarget } = this;
                dropTarget.addEventListener('dragenter', this[dragEnterHandler]);
                dropTarget.addEventListener('dragleave', this[dragLeaveHandler]);
                dropTarget.addEventListener('dragover', this[dragOverHandler]);
                dropTarget.addEventListener('drop', this[dropHandler]);
                super.connectedCallback();
            }
            disconnectedCallback() {
                const { dropTarget } = this;
                dropTarget.removeEventListener('dragenter', this[dragEnterHandler]);
                dropTarget.removeEventListener('dragleave', this[dragLeaveHandler]);
                dropTarget.removeEventListener('dragover', this[dragOverHandler]);
                dropTarget.removeEventListener('drop', this[dropHandler]);
                super.disconnectedCallback();
            }
            /**
             * Processes dropped to the page files
             * @param files The list of dropped files
             * @abstract This is to be implemented by the platform bindings
             */
            async processDroppedFiles(files) {
                // ...
            }
            /**
             * @returns The template for the drop file message
             */
            dropTargetTemplate() {
                return html `
        <div class="drop-info">
          <ui-icon icon="fileDownload" class="drop-icon"></ui-icon>
          <p class="drop-message">Drop the file here</p>
        </div>
      `;
            }
            [(_dropTargetActive_decorators = [property({ type: Boolean })], dragEnterHandler)](e) {
                if (!e.dataTransfer) {
                    return;
                }
                if (![...e.dataTransfer.types].includes('Files')) {
                    return;
                }
                e.preventDefault();
                this.dropTarget.classList.add('drop-target');
                this.dropTargetActive = true;
                e.dataTransfer.effectAllowed = 'copy';
            }
            [dragLeaveHandler](e) {
                if (!e.dataTransfer) {
                    return;
                }
                if (![...e.dataTransfer.types].includes('Files')) {
                    return;
                }
                const node = e.target;
                if (node.nodeType !== Node.ELEMENT_NODE) {
                    return;
                }
                if (node !== this.dropTarget && !node.classList.contains('drop-info')) {
                    return;
                }
                e.preventDefault();
                this.dropTarget.classList.remove('drop-target');
                this.dropTargetActive = false;
            }
            [dragOverHandler](e) {
                if (!e.dataTransfer) {
                    return;
                }
                if (![...e.dataTransfer.types].includes('Files')) {
                    return;
                }
                const node = e.target;
                if (node.nodeType !== Node.ELEMENT_NODE) {
                    return;
                }
                if (node !== this.dropTarget && !node.classList.contains('drop-info')) {
                    return;
                }
                e.preventDefault();
                this.dropTarget.classList.add('drop-target');
                this.dropTargetActive = true;
            }
            [dropHandler](e) {
                if (!e.dataTransfer) {
                    return;
                }
                if (![...e.dataTransfer.types].includes('Files')) {
                    return;
                }
                e.preventDefault();
                this.dropTarget.classList.remove('drop-target');
                this.dropTargetActive = false;
                this.processDroppedFiles(e.dataTransfer.files);
            }
        };
    })();
    return MyMixinClass;
};
//# sourceMappingURL=FileDropMixin.js.map