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;
};
import { UmbDocumentItemRepository } from '../../../item/index.js';
import { UMB_DOCUMENT_PICKER_MODAL } from '../../../constants.js';
import { css, customElement, html, property, repeat, state } from '../../../../../../external/lit/index.js';
import { UmbLitElement } from '../../../../../core/lit-element/index.js';
import { UMB_MODAL_MANAGER_CONTEXT } from '../../../../../core/modal/index.js';
import { UmbChangeEvent, UmbSelectedEvent } from '../../../../../core/event/index.js';
import { umbExtensionsRegistry } from '../../../../../core/extension-registry/index.js';
import { UUIFormControlMixin } from '../../../../../../external/uui/index.js';
import { UMB_ENTITY_USER_PERMISSION_MODAL, } from '../../../../../user/user-permission/index.js';
let UmbInputDocumentGranularUserPermissionElement = class UmbInputDocumentGranularUserPermissionElement extends UUIFormControlMixin(UmbLitElement, '') {
    #permissions;
    get permissions() {
        return this.#permissions;
    }
    set permissions(value) {
        this.#permissions = value;
        const uniques = value.map((item) => item.document.id);
        this.#observePickedDocuments(uniques);
    }
    #documentItemRepository;
    #modalManagerContext;
    #documentPickerModalContext;
    #entityUserPermissionModalContext;
    constructor() {
        super();
        this.#permissions = [];
        this.fallbackPermissions = [];
        this.#documentItemRepository = new UmbDocumentItemRepository(this);
        this.consumeContext(UMB_MODAL_MANAGER_CONTEXT, (instance) => (this.#modalManagerContext = instance));
    }
    getFormElement() {
        return undefined;
    }
    async #observePickedDocuments(uniques) {
        const { asObservable } = await this.#documentItemRepository.requestItems(uniques);
        this.observe(asObservable?.(), (items) => {
            this._items = items;
        }, 'observeItems');
    }
    async #editGranularPermission(item) {
        const currentPermissionVerbs = this.#getPermissionForDocument(item.unique)?.verbs ?? [];
        const result = await this.#selectEntityUserPermissionsForDocument(item, currentPermissionVerbs);
        // don't do anything if the verbs have not been updated
        if (JSON.stringify(result) === JSON.stringify(currentPermissionVerbs))
            return;
        // update permission with new verbs
        this.permissions = this.#permissions.map((permission) => {
            if (permission.document.id === item.unique) {
                return {
                    ...permission,
                    verbs: result,
                };
            }
            return permission;
        });
        this.dispatchEvent(new UmbChangeEvent());
    }
    async #addGranularPermission() {
        this.#documentPickerModalContext = this.#modalManagerContext?.open(this, UMB_DOCUMENT_PICKER_MODAL, {
            data: {
                hideTreeRoot: true,
                // prevent already selected items to be picked again
                // TODO: this type is wrong. It should be the tree item type
                pickableFilter: (treeItem) => !this._items?.map((i) => i.unique).includes(treeItem.unique),
            },
        });
        this.#documentPickerModalContext?.addEventListener(UmbSelectedEvent.TYPE, async (event) => {
            const selectedEvent = event;
            const unique = selectedEvent.unique;
            if (!unique)
                return;
            const documentItem = await this.#requestDocumentItem(unique);
            this.#selectEntityUserPermissionsForDocument(documentItem).then((result) => {
                this.#documentPickerModalContext?.reject();
                const permissionItem = {
                    $type: 'DocumentPermissionPresentationModel',
                    document: { id: unique },
                    verbs: result,
                };
                this.permissions = [...this.#permissions, permissionItem];
                this.dispatchEvent(new UmbChangeEvent());
            }, () => {
                this.#documentPickerModalContext?.reject();
            });
        });
    }
    async #requestDocumentItem(unique) {
        if (!unique)
            throw new Error('Could not open permissions modal, no unique was provided');
        const { data } = await this.#documentItemRepository.requestItems([unique]);
        const documentItem = data?.[0];
        if (!documentItem)
            throw new Error('No document item found');
        return documentItem;
    }
    async #selectEntityUserPermissionsForDocument(item, allowedVerbs = []) {
        // TODO: get correct variant name
        const name = item.variants[0]?.name;
        const headline = name ? `Permissions for ${name}` : 'Permissions';
        const fallbackVerbs = this.#getFallbackPermissionVerbsForEntityType(item.entityType);
        const value = allowedVerbs.length > 0 ? { allowedVerbs } : undefined;
        this.#entityUserPermissionModalContext = this.#modalManagerContext?.open(this, UMB_ENTITY_USER_PERMISSION_MODAL, {
            data: {
                entityType: item.entityType,
                headline,
                preset: {
                    allowedVerbs: fallbackVerbs,
                },
            },
            value,
        });
        try {
            // When the modal is submitted we return the new value from the modal
            const value = await this.#entityUserPermissionModalContext?.onSubmit();
            return value?.allowedVerbs;
        }
        catch {
            // When the modal is rejected we return the current value
            return allowedVerbs;
        }
    }
    #removeGranularPermission(item) {
        const permission = this.#getPermissionForDocument(item.unique);
        if (!permission)
            return;
        this.permissions = this.#permissions.filter((v) => JSON.stringify(v) !== JSON.stringify(permission));
        this.dispatchEvent(new UmbChangeEvent());
    }
    render() {
        return html `${this.#renderItems()} ${this.#renderAddButton()}`;
    }
    #renderItems() {
        if (!this._items)
            return;
        return html `
			<uui-ref-list>
				${repeat(this._items, (item) => item.unique, (item) => this.#renderRef(item))}
			</uui-ref-list>
		`;
    }
    #renderAddButton() {
        return html `<uui-button
			id="btn-add"
			look="placeholder"
			@click=${this.#addGranularPermission}
			label=${this.localize.term('general_add')}></uui-button>`;
    }
    #renderRef(item) {
        if (!item.unique)
            return;
        // TODO: get correct variant name
        const name = item.variants[0]?.name;
        const permissionNames = this.#getPermissionNamesForDocument(item.unique);
        return html `
			<uui-ref-node .name=${name} .detail=${permissionNames || ''}>
				${this.#renderIcon(item)} ${this.#renderIsTrashed(item)}
				<uui-action-bar slot="actions">
					${this.#renderEditButton(item)} ${this.#renderRemoveButton(item)}
				</uui-action-bar>
			</uui-ref-node>
		`;
    }
    #renderIcon(item) {
        if (!item.documentType.icon)
            return;
        return html `<uui-icon slot="icon" name=${item.documentType.icon}></uui-icon>`;
    }
    #renderIsTrashed(item) {
        if (!item.isTrashed)
            return;
        return html `<uui-tag size="s" slot="tag" color="danger">Trashed</uui-tag>`;
    }
    #renderEditButton(item) {
        return html `
			<uui-button
				@click=${() => this.#editGranularPermission(item)}
				label=${this.localize.term('general_edit')}></uui-button>
		`;
    }
    #renderRemoveButton(item) {
        return html `<uui-button
			@click=${() => this.#removeGranularPermission(item)}
			label=${this.localize.term('general_remove')}></uui-button>`;
    }
    #getPermissionForDocument(unique) {
        return this.#permissions?.find((permission) => permission.document.id === unique);
    }
    #getPermissionNamesForDocument(unique) {
        const permission = this.#getPermissionForDocument(unique);
        if (!permission)
            return;
        return umbExtensionsRegistry
            .getByTypeAndFilter('entityUserPermission', (manifest) => manifest.meta.verbs.every((verb) => permission.verbs.includes(verb)))
            .map((m) => {
            const manifest = m;
            return manifest.meta.label ? this.localize.string(manifest.meta.label) : manifest.name;
        })
            .join(', ');
    }
    #getFallbackPermissionVerbsForEntityType(entityType) {
        // get all permissions that are allowed for the entity type and have at least one of the fallback permissions
        // this is used to determine the default permissions for a document
        const verbs = umbExtensionsRegistry
            .getByTypeAndFilter('entityUserPermission', (manifest) => manifest.forEntityTypes.includes(entityType) &&
            this.fallbackPermissions.map((verb) => manifest.meta.verbs.includes(verb)).includes(true))
            .flatMap((permission) => permission.meta.verbs);
        // ensure that the verbs are unique
        return [...new Set([...verbs])];
    }
    static { this.styles = [
        css `
			#btn-add {
				width: 100%;
			}
		`,
    ]; }
};
__decorate([
    property({ type: Array, attribute: false })
], UmbInputDocumentGranularUserPermissionElement.prototype, "fallbackPermissions", void 0);
__decorate([
    state()
], UmbInputDocumentGranularUserPermissionElement.prototype, "_items", void 0);
UmbInputDocumentGranularUserPermissionElement = __decorate([
    customElement('umb-input-document-granular-user-permission')
], UmbInputDocumentGranularUserPermissionElement);
export { UmbInputDocumentGranularUserPermissionElement };
export default UmbInputDocumentGranularUserPermissionElement;
