import { EventUtils } from "@api-client/core/build/browser.js";
import { html } from "lit";
import '@github/relative-time-element';
import { navigate } from "../../../lib/route.js";
import { SnackNotifications } from "../../../ui/notification/SnackNotifications.js";
import { DataTable } from "../../../ui/table/DataTable.js";
import { fileIcon } from "../../../elements/store/FilesLib.js";
import '../../../define/ui/ui-icon.js';
/**
 * A class that specializes in rendering the list of trash in HTTP Client.
 */
export class TrashPage {
    get deleteItems() {
        const { deleteKeys, files } = this;
        if (!deleteKeys) {
            return [];
        }
        const result = [];
        deleteKeys.forEach((key) => {
            const item = files.find(i => i.key === key);
            if (item) {
                result.push(item);
            }
        });
        return result;
    }
    constructor(screen) {
        this.screen = screen;
        this.files = [];
        this.dt = new DataTable(() => this.files, { ariaLabel: 'Trashed files' });
        this.dt.addEventListener('empty', this.renderEmptyTable.bind(this));
        this.dt.addEventListener('header', this.renderTableHeader.bind(this));
        this.dt.addEventListener('item', this.renderTableItem.bind(this));
        this.itemOptionsSelectHandler = this.itemOptionsSelectHandler.bind(this);
        this.cancelDeleteAllDialog = this.cancelDeleteAllDialog.bind(this);
        this.deleteAllHandler = this.deleteAllHandler.bind(this);
        this.cancelDeleteFilesDialog = this.cancelDeleteFilesDialog.bind(this);
        this.deleteFilesHandler = this.deleteFilesHandler.bind(this);
        this.openEmptyAllDialogHandler = this.openEmptyAllDialogHandler.bind(this);
    }
    handleFileEvent(event) {
        switch (event.operation) {
            case 'created':
                this.handleTrashAdded(event.data);
                break;
            case 'deleted':
                this.handleTrashRemoved(event.key);
                break;
            default:
        }
    }
    handleTrashAdded(item) {
        this.files.push(item);
        this.files.sort(this.filesSortFunction.bind(this));
        this.screen.render();
    }
    handleTrashRemoved(key) {
        const index = this.files.findIndex(i => i.key === key);
        if (index === -1) {
            return;
        }
        this.files.splice(index, 1);
        this.screen.render();
    }
    async refresh() {
        this.resetList();
        this.screen.render();
        await this.readFiles();
    }
    resetList() {
        this.files = [];
        this.cursor = undefined;
    }
    async readFiles() {
        const { selectedSpace } = this.screen;
        if (!selectedSpace) {
            return;
        }
        if (this.readingFiles) {
            return;
        }
        this.readingFiles = true;
        const { cursor: currentCursor } = this;
        const opts = {
            space: selectedSpace,
            descending: true,
        };
        if (currentCursor) {
            opts.cursor = currentCursor;
        }
        try {
            const result = await this.screen.bindings.store.trash.list(opts);
            const { items, cursor } = result;
            this.files = this.files.concat(items).sort(this.filesSortFunction.bind(this));
            this.cursor = cursor;
        }
        finally {
            this.readingFiles = false;
        }
        this.screen.render();
    }
    /**
     * Sorts files on the list.
     *
     * Folders are always on top.
     */
    filesSortFunction(a, b) {
        return b.info.time - a.info.time;
    }
    itemOptionsSelectHandler(e) {
        const item = e.detail.item;
        const list = e.target;
        const operation = item.dataset.option;
        const key = list.dataset.key;
        if (!key || !operation) {
            return;
        }
        if (operation === 'restore') {
            this.restoreItem(key);
        }
        else if (operation === 'delete') {
            this.deleteKeys = [key];
            this.screen.render();
            this.screen.openDialog('deleteFilesDialog');
        }
    }
    async restoreItem(key) {
        const { bindings, selectedSpace } = this.screen;
        if (!selectedSpace) {
            throw new Error(`Invalid state: Folder is not selected.`);
        }
        const record = await bindings.store.trash.restore(key);
        const file = record.item;
        const parentId = file.parents && file.parents.length ? file.parents[file.parents.length - 1] : undefined;
        SnackNotifications.notify(`Restored file: ${file.info.name}`, {
            actionLabel: 'Go to file location',
            actionCallback: () => {
                if (parentId) {
                    navigate('files', parentId);
                }
                else {
                    navigate('files');
                }
            },
        });
    }
    async deleteItem(key) {
        const { bindings, selectedSpace } = this.screen;
        if (!selectedSpace) {
            throw new Error(`Invalid state: Folder is not selected.`);
        }
        await bindings.store.trash.delete(key);
    }
    openEmptyAllDialogHandler() {
        this.screen.openDialog('deleteAllDialog');
    }
    cancelDeleteAllDialog() {
        this.screen.closeDialog('deleteAllDialog');
    }
    deleteAllHandler() {
        this.screen.closeDialog('deleteAllDialog');
        const { bindings, selectedSpace } = this.screen;
        if (!selectedSpace) {
            throw new Error(`Invalid state: Folder is not selected.`);
        }
        bindings.store.trash.empty(selectedSpace);
    }
    cancelDeleteFilesDialog() {
        this.deleteKeys = undefined;
        this.screen.closeDialog('deleteFilesDialog');
    }
    deleteFilesHandler() {
        this.screen.closeDialog('deleteFilesDialog');
        this.screen.render();
        const { deleteKeys } = this;
        this.deleteKeys = undefined;
        if (!deleteKeys || !deleteKeys.length) {
            return;
        }
        deleteKeys.forEach(k => this.deleteItem(k));
    }
    render() {
        return html `
    <div class="section-header">
      <h2 class="headline-small">Trash</h2>
      <div class="spacer"></div>
      ${this.renderEmptyTrash()}
    </div>
    ${this.renderTrashTable()}
    ${this.renderDeleteAllDialog()}
    ${this.renderDeleteFilesDialog()}
    `;
    }
    renderEmptyTrash() {
        const { files } = this;
        const disabled = !files || !files.length;
        return html `
    <ui-button type="outlined" ?disabled="${disabled}" @click="${this.openEmptyAllDialogHandler}">
      <ui-icon icon="deleteOutline" slot="icon"></ui-icon>
      Empty trash
    </ui-button>
    `;
    }
    renderTrashTable() {
        return this.dt.render();
    }
    renderEmptyTable() {
        return html `
    <p>The trash bin is empty.</p>
    `;
    }
    renderTableHeader() {
        const name = this.dt.header('Name', { class: 'name-cell' });
        const deleted = this.dt.header('Deleted', { class: 'updated-cell' });
        const menu = this.dt.header(html `<span hidden>Menu</span>`, { class: 'menu-cell' });
        return [name, deleted, menu];
    }
    renderTableItem(item) {
        const { kind, name, info } = item;
        const icon = fileIcon(item);
        const nameCell = this.dt.cell(html `
      ${icon ? html `<ui-icon icon="${icon}" class="cell-icon"></ui-icon>` : ''}
      ${name || 'Unnamed file'}
    `, { class: 'name-cell', data: { kind } });
        const deleted = this.dt.cell(html `
      <relative-time datetime="${new Date(info.time).toISOString()}"></relative-time>
    `, { class: 'updated-cell' });
        const menu = this.dt.cell(this.renderItemOptions(item), { class: 'menu-cell' });
        return [nameCell, deleted, menu];
    }
    renderItemOptions(item) {
        return html `
    <ui-dropdown-list
      horizontalAlign="auto"
      verticalAlign="auto"
      closeOnOutsideClick
      @mousedown="${EventUtils.cancelEvent}" 
      @mouseup="${EventUtils.cancelEvent}" 
      @click="${EventUtils.cancelEvent}"
      @dblclick="${EventUtils.cancelEvent}"
      @select="${this.itemOptionsSelectHandler}"
      data-key="${item.key}"
    >
      <ui-icon-button title="Project options" aria-label="Activate for more options">
        <ui-icon icon="moreVert"></ui-icon>
      </ui-icon-button>
      <ui-list slot="dropdown" role="menu">
        <ui-list-item image="icon" data-option="restore" role="menuitem" title="Restores the file to its original folder.">
          <ui-icon icon="restoreFromTrash" slot="start"></ui-icon>
          Restore
        </ui-list-item>
        <ui-list-item image="icon" data-option="delete" role="menuitem" title="Permanently deleted the item.">
          <ui-icon icon="deleteOutline" slot="start"></ui-icon>
          Delete forever
        </ui-list-item>
      </ui-list>
    </ui-dropdown-list>
    `;
    }
    renderDeleteAllDialog() {
        return html `
    <dialog id="deleteAllDialog" class="warning">
      <h3>Empty Trash?</h3>
      <div>
        <p class="body-medium">
          This will permanently delete all files in the trash.
        </p>
      </div>
      <div class="dialog-buttons">
        <ui-button type="text" value="cancel" @click="${this.cancelDeleteAllDialog}">Cancel</ui-button>
        <ui-button type="text" value="delete" @click="${this.deleteAllHandler}">Delete</ui-button>
      </div>
    </dialog>
    `;
    }
    renderDeleteFilesDialog() {
        const { deleteItems } = this;
        return html `
    <dialog id="deleteFilesDialog" class="warning">
      <h3>Delete Forever?</h3>
      <div>
        ${deleteItems.length > 1 ? this.renderDeleteMultiFile(deleteItems) : this.renderDeleteSingleFile(deleteItems[0])}
      </div>
      <div class="dialog-buttons">
        <ui-button type="text" value="cancel" @click="${this.cancelDeleteFilesDialog}">Cancel</ui-button>
        <ui-button type="text" value="delete" @click="${this.deleteFilesHandler}">Delete</ui-button>
      </div>
    </dialog>
    `;
    }
    renderDeleteSingleFile(item) {
        if (!item) {
            return html `
      <p class="body-medium">Invalid state. Couldn't find files to delete.</p>
      `;
        }
        return html `
    <p class="body-medium">
      <b>"${item.name}"</b> will be deleted forever and you won't be able to restore it.
    </p>
    `;
    }
    renderDeleteMultiFile(items) {
        return html `
    <p class="body-medium">
      The following files will be deleted forever and you won't be able to restore them:
    </p>
    <ui-divider></ui-divider>
    <ul>
      ${items.map(i => html `<li>${i.name}</li>`)}
    </ul>
    <ui-divider></ui-divider>
    `;
    }
}
//# sourceMappingURL=Trash.page.js.map