var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
    if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
    if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
    return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
};
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
    if (kind === "m") throw new TypeError("Private method is not writable");
    if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
    if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
    return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
};
var _FileUploadDropper_instances, _FileUploadDropper_allowedMimes, _FileUploadDropper_acceptPatterns, _FileUploadDropper_pickFile, _FileUploadDropper_processFileInput, _FileUploadDropper_processDrop, _FileUploadDropper_processFileList, _FileUploadDropper_clearError, _FileUploadDropper_dragStart, _FileUploadDropper_dragEnd, _FileUploadDropper_validateFileList, _FileUploadDropper_validateFileCount, _FileUploadDropper_validateFileTypes, _FileUploadDropper_mimeAllowed, _FileUploadDropper_extractWildcardTypes;
import { css, html, LitElement } from 'lit';
import { customElement, property, state } from 'lit/decorators.js';
import { classMap } from 'lit-html/directives/class-map.js';
import { ifDefined } from 'lit-html/directives/if-defined.js';
import { fileAccessContext, flattenAcceptTypes, hasFileAccessAPI, tryGetAsFilesystemHandle } from '../../utils/file-access-api.js';
import { cssReset } from '../../utils/css-reset.js';
import { Bubble } from '../../utils/bubble.js';
let FileUploadDropper = class FileUploadDropper extends LitElement {
    constructor() {
        super(...arguments);
        _FileUploadDropper_instances.add(this);
        this.acceptTypes = [];
        this.multiple = false;
        this._dragging = false;
        _FileUploadDropper_allowedMimes.set(this, []);
        _FileUploadDropper_acceptPatterns.set(this, []);
        /**
         * Uses File Access API to get FileSystemFileHandles
         */
        _FileUploadDropper_pickFile.set(this, async () => {
            const fileHandles = await fileAccessContext.showOpenFilePicker({
                ...(this.id ? { id: this.id } : {}),
                types: this.acceptTypes,
                multiple: this.multiple
            });
            if (fileHandles.length > 0) {
                this.dispatchEvent(Bubble('files-selected', { fileHandles }));
            }
            else {
                this.dispatchEvent(Bubble('cancelled', undefined));
            }
        }
        /**
         * Handles the <input type=file> field as a fallback
         */
        );
        /**
         * Handles the <input type=file> field as a fallback
         */
        _FileUploadDropper_processFileInput.set(this, async (ev) => {
            if (ev.currentTarget.files) {
                await __classPrivateFieldGet(this, _FileUploadDropper_processFileList, "f").call(this, ev.currentTarget.files);
            }
        }
        /**
         * Handles the drag'n'drop result
         */
        );
        /**
         * Handles the drag'n'drop result
         */
        _FileUploadDropper_processDrop.set(this, async (ev) => {
            ev.preventDefault();
            __classPrivateFieldGet(this, _FileUploadDropper_dragEnd, "f").call(this);
            if (!ev.dataTransfer || !__classPrivateFieldGet(this, _FileUploadDropper_instances, "m", _FileUploadDropper_validateFileList).call(this, ev.dataTransfer.files)) {
                return;
            }
            if (hasFileAccessAPI) {
                const fileHandles = [];
                for (let index = 0; index < ev.dataTransfer.items.length; index++) {
                    const item = ev.dataTransfer.items[index];
                    if (item) {
                        const handle = await tryGetAsFilesystemHandle(item);
                        if (handle) {
                            if (handle.kind === 'file') {
                                fileHandles.push(handle);
                            }
                            else {
                                this._errorMessage = 'Directories cannot be dropped here.';
                                return;
                            }
                        }
                    }
                }
                this.dispatchEvent(Bubble('files-selected', { fileHandles }));
            }
            else {
                await __classPrivateFieldGet(this, _FileUploadDropper_processFileList, "f").call(this, ev.dataTransfer.files);
            }
        });
        _FileUploadDropper_processFileList.set(this, async (fileList) => {
            if (!__classPrivateFieldGet(this, _FileUploadDropper_instances, "m", _FileUploadDropper_validateFileList).call(this, fileList)) {
                return;
            }
            __classPrivateFieldGet(this, _FileUploadDropper_clearError, "f").call(this);
            const files = [];
            for (let index = 0; index < fileList.length; index++) {
                const file = fileList[index];
                if (file) {
                    files.push(file);
                }
            }
            this.dispatchEvent(Bubble('files-selected', { files }));
        });
        _FileUploadDropper_clearError.set(this, () => {
            this._errorMessage = undefined;
        });
        _FileUploadDropper_dragStart.set(this, (ev) => {
            if (ev.type === 'dragover') {
                ev.preventDefault();
            }
            __classPrivateFieldGet(this, _FileUploadDropper_clearError, "f").call(this);
            this._dragging = true;
        });
        _FileUploadDropper_dragEnd.set(this, () => {
            this._dragging = false;
        });
    }
    update(changedProperties) {
        super.update(changedProperties);
        if (changedProperties.has('acceptTypes')) {
            this._accept = flattenAcceptTypes(this.acceptTypes);
            __classPrivateFieldSet(this, _FileUploadDropper_acceptPatterns, __classPrivateFieldGet(this, _FileUploadDropper_instances, "m", _FileUploadDropper_extractWildcardTypes).call(this), "f");
        }
    }
    render() {
        return html `
      <input
        type="file"
        id="fileInput"
        accept="${ifDefined(this._accept)}"
        ?multiple="${this.multiple}"
        @change=${__classPrivateFieldGet(this, _FileUploadDropper_processFileInput, "f")}
      />
      <label for="${hasFileAccessAPI ? '' : 'fileInput'}">
        <div
          id="fileDrop"
          class="${classMap({ dragenter: this._dragging })}"
          @click=${hasFileAccessAPI ? __classPrivateFieldGet(this, _FileUploadDropper_pickFile, "f") : undefined}
          @dragenter=${__classPrivateFieldGet(this, _FileUploadDropper_dragStart, "f")}
          @dragover=${__classPrivateFieldGet(this, _FileUploadDropper_dragStart, "f")}
          @dragleave=${__classPrivateFieldGet(this, _FileUploadDropper_dragEnd, "f")}
          @dragend=${__classPrivateFieldGet(this, _FileUploadDropper_dragEnd, "f")}
          @drop=${__classPrivateFieldGet(this, _FileUploadDropper_processDrop, "f")}
        >
          <slot></slot>
          <span id="errorMessage">${this._errorMessage}</span>
        </div>
      </label>
    `;
    }
};
_FileUploadDropper_allowedMimes = new WeakMap();
_FileUploadDropper_acceptPatterns = new WeakMap();
_FileUploadDropper_pickFile = new WeakMap();
_FileUploadDropper_processFileInput = new WeakMap();
_FileUploadDropper_processDrop = new WeakMap();
_FileUploadDropper_processFileList = new WeakMap();
_FileUploadDropper_clearError = new WeakMap();
_FileUploadDropper_dragStart = new WeakMap();
_FileUploadDropper_dragEnd = new WeakMap();
_FileUploadDropper_instances = new WeakSet();
_FileUploadDropper_validateFileList = function _FileUploadDropper_validateFileList(fileList) {
    return (__classPrivateFieldGet(this, _FileUploadDropper_instances, "m", _FileUploadDropper_validateFileCount).call(this, fileList) && __classPrivateFieldGet(this, _FileUploadDropper_instances, "m", _FileUploadDropper_validateFileTypes).call(this, fileList));
};
_FileUploadDropper_validateFileCount = function _FileUploadDropper_validateFileCount(fileList) {
    if (fileList.length > 0) {
        if (this.multiple) {
            return fileList.length >= 1;
        }
        return fileList.length === 1;
    }
    return false;
};
_FileUploadDropper_validateFileTypes = function _FileUploadDropper_validateFileTypes(fileList) {
    if (this.acceptTypes.length === 0) {
        return true;
    }
    for (let index = 0; index < fileList.length; index++) {
        const file = fileList[index];
        if (file && !__classPrivateFieldGet(this, _FileUploadDropper_instances, "m", _FileUploadDropper_mimeAllowed).call(this, file.type)) {
            this._errorMessage = `Invalid file type provided: ${file.type}`;
            return false;
        }
    }
    return true;
};
_FileUploadDropper_mimeAllowed = function _FileUploadDropper_mimeAllowed(mimetype) {
    if (!(mimetype in __classPrivateFieldGet(this, _FileUploadDropper_allowedMimes, "f"))) {
        for (let pattern of __classPrivateFieldGet(this, _FileUploadDropper_acceptPatterns, "f")) {
            if (pattern.test(mimetype)) {
                return true;
            }
        }
        return false;
    }
    return true;
};
_FileUploadDropper_extractWildcardTypes = function _FileUploadDropper_extractWildcardTypes() {
    return this.acceptTypes.flatMap(type => Object.keys(type.accept).flatMap(mimetype => {
        if (mimetype.includes('*')) {
            return new RegExp(mimetype.split('*').join('.*'));
        }
        __classPrivateFieldGet(this, _FileUploadDropper_allowedMimes, "f").push(mimetype);
        return [];
    }));
};
FileUploadDropper.styles = css `
    ${cssReset}

    input[type='file'] {
      display: none;
    }

    #fileDrop {
      border: 3px dashed black;
      border-radius: 8px;
      padding: var(--space);
      display: flex;
      flex-direction: column;
      align-items: center;
      cursor: pointer;
    }

    #fileDrop.dragenter {
      border-color: blue;
    }

    #errorMessage {
      color: red;
      font-size: 0.9em;
    }
  `;
__decorate([
    property({ attribute: 'accept-types', type: Array, reflect: true })
], FileUploadDropper.prototype, "acceptTypes", void 0);
__decorate([
    property({ attribute: 'multiple', type: Boolean, reflect: true })
], FileUploadDropper.prototype, "multiple", void 0);
__decorate([
    state()
], FileUploadDropper.prototype, "_dragging", void 0);
__decorate([
    state()
], FileUploadDropper.prototype, "_errorMessage", void 0);
__decorate([
    state()
], FileUploadDropper.prototype, "_accept", void 0);
FileUploadDropper = __decorate([
    customElement('file-upload-dropper')
], FileUploadDropper);
export { FileUploadDropper };
//# sourceMappingURL=file-upload-dropper.js.map