import { __decorate } from "tslib";
import { FolderKind } from "@api-client/core/build/browser.js";
import { html, nothing } from "lit";
import { eventOptions, property, query, state } from "lit/decorators.js";
import { classMap } from "lit/directives/class-map.js";
import ApiElement from "../ApiElement.js";
import styles from './FilePicker.styles.js';
import { fileIcon } from "./FilesLib.js";
import { FileSystem } from "../../store/FileSystem.js";
import '../../define/ui/ui-divider.js';
import '../../define/ui/ui-button.js';
import '../../define/ui/ui-icon-button.js';
import '../../define/ui/ui-icon.js';
import '../../define/ui/ui-list.js';
import '../../define/ui/ui-list-item.js';
import '../../define/ui/ui-progress.js';
/**
 * A portable element that allow to pick a file from the Store.
 *
 * @fires close - When a file is selected or the user cancelled the dialog. The detail object is the picked file object. Note, this event bubbles.
 * @fires querycomplete - When the page of results was loaded.
 */
export default class FilePicker extends ApiElement {
    static get styles() {
        return styles;
    }
    /**
     * The key of the parent folder to query for files.
     * @attribute
     */
    get folder() {
        return this.fs.parent;
    }
    set folder(value) {
        this.fs.selectFolder(value);
    }
    /**
     * The page limit. Defaults to the store defaults.
     * @attribute
     */
    set limit(value) {
        this.fs.limit = value;
    }
    get limit() {
        return this.fs.limit;
    }
    /**
     * The timeout for the page query debouncer.
     * @attribute
     */
    get debounceTimeout() {
        return this.fs.debounceTimeout;
    }
    set debounceTimeout(value) {
        this.fs.debounceTimeout = value || 0;
    }
    /**
     * The list of file kinds to list.
     * Folders are always included.
     */
    get kinds() {
        return this.fs.kinds;
    }
    set kinds(value) {
        this.fs.kinds = value;
        this.fs.resetList();
        this.fs.debounceQuery();
    }
    get selectedKey() {
        return this.selectedFile?.key;
    }
    constructor() {
        super();
        this.fs = new FileSystem();
        this.fs.eventsTarget = this;
        this.fs.addEventListener('change', () => this.requestUpdate());
        this.fs.addEventListener('error', (e) => {
            const event = e;
            this.errorMessage = event.detail;
        });
        this.fs.addEventListener('querycomplete', () => {
            this.dispatchEvent(new Event('querycomplete'));
        });
        this.fs.addEventListener('delete', (e) => {
            const event = e;
            if (this.selectedFile && this.selectedFile.key === event.detail) {
                this.selectedFile = undefined;
            }
        });
    }
    connectedCallback() {
        super.connectedCallback();
        this.fs.observe();
        if (!this.manualQuery) {
            this.fs.debounceQuery();
        }
        if (!this.hasAttribute('tabindex')) {
            this.setAttribute('tabindex', '0');
        }
    }
    disconnectedCallback() {
        super.disconnectedCallback();
        this.fs.unobserve();
    }
    focus(options) {
        const { list } = this;
        if (list) {
            list.focus(options);
        }
    }
    handleFileSelect(e) {
        // this prevents the dropdown list to close the UI.
        e.preventDefault();
        const file = this.fs.files[e.detail.index];
        if (!file) {
            return;
        }
        if (file.kind === FolderKind) {
            this.fs.selectFolder(file.key);
            this.selectedFile = undefined;
            return;
        }
        this.selectedFile = file;
    }
    handleParentUp() {
        this.fs.parentUp();
        this.selectedFile = undefined;
    }
    notifyClose(canceled) {
        if (!canceled && !this.selectedFile) {
            return;
        }
        const detail = {
            canceled,
        };
        if (!canceled) {
            detail.file = this.selectedFile;
        }
        // this event bubbles so any dropdown on the way can close itself.
        const e = new CustomEvent('close', {
            bubbles: true,
            cancelable: true,
            composed: true,
            detail,
        });
        this.dispatchEvent(e);
    }
    handleSelect() {
        this.notifyClose(false);
    }
    handleCancel() {
        this.notifyClose(true);
    }
    handleListScroll(e) {
        const list = e.target;
        if (this.fs.isListEnd(list)) {
            this.fs.debounceQuery();
        }
    }
    render() {
        return html `
    <div class="content">
      ${this.renderHeader()}
      <ui-divider></ui-divider>
      ${this.renderFiles()}
      ${this.errorMessage ? html `<p class="error">${this.errorMessage}</p>` : nothing}
      <ui-divider></ui-divider>
      ${this.renderActions()}
    </div>
    `;
    }
    renderHeader() {
        const { breadcrumbs = [], reading } = this.fs;
        let content;
        let withIcon = false;
        if (!breadcrumbs.length) {
            content = html `<span class="title-large label">My files</span>`;
        }
        else {
            withIcon = true;
            const [parent] = breadcrumbs;
            content = html `
        <ui-icon-button aria-label="Open parent folder" @click="${this.handleParentUp}" class="back-button">
          <ui-icon role="presentation" icon="arrowBack"></ui-icon>
        </ui-icon-button>
        <span class="title-large label">${parent.name}</span>
      `;
        }
        const classes = {
            header: true,
            withIcon,
        };
        return html `
    <div class="${classMap(classes)}">
      ${content}
      ${reading ? html `<ui-progress indeterminate class="progress"></ui-progress>` : nothing}
    </div>
    `;
    }
    renderFiles() {
        const { files } = this.fs;
        if (!files || !files.length) {
            return this.renderEmptyList();
        }
        return html `
    <ui-list class="list" role="menu" @select="${this.handleFileSelect}" selectActive @scroll="${this.handleListScroll}">
      ${files.map(item => this.renderFileItem(item))}
    </ui-list>
    `;
    }
    renderEmptyList() {
        return html `
    <p class="no-files body-large">No files in this view.</p>
    `;
    }
    renderFileItem(item) {
        const icon = fileIcon(item);
        return html `
    <ui-list-item role="menuitem" data-key="${item.key}" data-kind="${item.kind}">
      ${icon ? html `<ui-icon icon="${icon}" class="file-icon"></ui-icon>` : nothing}
      ${item.info.name || 'Unnamed file'}
    </ui-list-item>
    `;
    }
    renderActions() {
        const { selectedFile } = this;
        const disableSelect = !selectedFile;
        return html `
    <div class="actions">
      <ui-button type="text" @click="${this.handleCancel}" value="cancel">Cancel</ui-button>
      <ui-button type="tonal" ?disabled="${disableSelect}" @click="${this.handleSelect}" value="select">Select</ui-button>
    </div>
    `;
    }
}
__decorate([
    property({ type: String, hasChanged: () => false })
], FilePicker.prototype, "folder", null);
__decorate([
    property({ type: Number, hasChanged: () => false })
], FilePicker.prototype, "limit", null);
__decorate([
    property({ type: Number, hasChanged: () => false })
], FilePicker.prototype, "debounceTimeout", null);
__decorate([
    property({ type: Array, hasChanged: () => false })
], FilePicker.prototype, "kinds", null);
__decorate([
    query('ui-list')
], FilePicker.prototype, "list", void 0);
__decorate([
    state()
], FilePicker.prototype, "selectedFile", void 0);
__decorate([
    state()
], FilePicker.prototype, "errorMessage", void 0);
__decorate([
    property({ type: Boolean })
], FilePicker.prototype, "manualQuery", void 0);
__decorate([
    eventOptions({ passive: true })
], FilePicker.prototype, "handleListScroll", null);
//# sourceMappingURL=FilePicker.element.js.map