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 { UMB_BLOCK_GRID_TYPE_WORKSPACE_MODAL } from '../../workspace/index.js';
import { UMB_BLOCK_GRID_TYPE } from '../../constants.js';
import { html, customElement, property, state, repeat, nothing, css, ifDefined, } from '../../../../../external/lit/index.js';
import { UmbTextStyles } from '../../../../core/style/index.js';
import { UmbLitElement } from '../../../../core/lit-element/index.js';
import { UMB_PROPERTY_CONTEXT, UMB_PROPERTY_DATASET_CONTEXT, } from '../../../../core/property/index.js';
import { UmbModalRouteRegistrationController } from '../../../../core/router/index.js';
import { UmbSorterController } from '../../../../core/sorter/index.js';
import { UmbChangeEvent } from '../../../../core/event/index.js';
import { umbConfirmModal } from '../../../../core/modal/index.js';
// TODO: This is across packages, how should we go about getting just a single element from another package? like here we just need the `umb-input-block-type` element.
import '../../../block-type/index.js';
/**
 * @element umb-property-editor-ui-block-grid-type-configuration
 */
let UmbPropertyEditorUIBlockGridTypeConfigurationElement = class UmbPropertyEditorUIBlockGridTypeConfigurationElement extends UmbLitElement {
    #sorter;
    #datasetContext;
    #blockTypeWorkspaceModalRegistration;
    #value;
    get value() {
        return this.#value;
    }
    set value(value) {
        this.#value = value ?? [];
        this.#mapValuesToBlockGroups();
    }
    #blockGroups;
    constructor() {
        super();
        this.#sorter = new UmbSorterController(this, {
            getUniqueOfElement: (element) => element.getAttribute('data-umb-group-key'),
            getUniqueOfModel: (modelEntry) => modelEntry.key,
            itemSelector: '.group',
            handleSelector: '.group-handle',
            containerSelector: '#groups',
            onChange: ({ model }) => {
                this._groupsWithBlockTypes = model;
            },
            onEnd: () => {
                // TODO: make one method for updating the blockGroupsDataSetValue:
                this.#datasetContext?.setPropertyValue('blockGroups', this._groupsWithBlockTypes.map((group) => ({ key: group.key, name: group.name })));
            },
        });
        this.#value = [];
        this._groupsWithBlockTypes = [];
        this._notGroupedBlockTypes = [];
        this.consumeContext(UMB_PROPERTY_CONTEXT, async (context) => {
            this._alias = context?.getAlias();
        });
        this.consumeContext(UMB_PROPERTY_DATASET_CONTEXT, async (context) => {
            this.#datasetContext = context;
            this.observe(await this.#datasetContext?.propertyValueByAlias('blockGroups'), (value) => {
                this.#blockGroups = value ?? [];
                this.#mapValuesToBlockGroups();
            }, '_observeBlockGroups');
        });
        this.#blockTypeWorkspaceModalRegistration = new UmbModalRouteRegistrationController(this, UMB_BLOCK_GRID_TYPE_WORKSPACE_MODAL)
            .addAdditionalPath(UMB_BLOCK_GRID_TYPE)
            .observeRouteBuilder((routeBuilder) => {
            const newpath = routeBuilder({});
            this._workspacePath = newpath;
        });
    }
    #mapValuesToBlockGroups() {
        if (!this.#blockGroups)
            return;
        // Map blocks that are not in any group, or in a group that does not exist
        this._notGroupedBlockTypes = this.#value.filter((block) => !block.groupKey || !this.#blockGroups.find((group) => group.key === block.groupKey));
        // Map blocks to the group they belong to
        this._groupsWithBlockTypes = this.#blockGroups.map((group) => {
            return { name: group.name, key: group.key, blocks: this.#value.filter((value) => value.groupKey === group.key) };
        });
        this.#sorter.setModel(this._groupsWithBlockTypes);
    }
    async #onChange(e, groupKey) {
        e.stopPropagation();
        const element = e.target;
        const value = element.value.map((x) => ({ ...x, groupKey }));
        if (groupKey) {
            // Update the specific group:
            this._groupsWithBlockTypes = this._groupsWithBlockTypes.map((group) => {
                if (group.key === groupKey) {
                    return { ...group, blocks: value };
                }
                return group;
            });
        }
        else {
            // Update the not grouped blocks:
            this._notGroupedBlockTypes = value;
        }
        this.#updateValue();
    }
    #updateValue() {
        this.value = [...this._notGroupedBlockTypes, ...this._groupsWithBlockTypes.flatMap((group) => group.blocks)];
        this.dispatchEvent(new UmbChangeEvent());
    }
    #updateBlockGroupsValue(groups) {
        this.#datasetContext?.setPropertyValue('blockGroups', groups);
    }
    #onCreate(e, groupKey) {
        const selectedElementType = e.detail.contentElementTypeKey;
        if (selectedElementType) {
            this.#blockTypeWorkspaceModalRegistration?.open({}, 'create/' + selectedElementType + '/' + (groupKey ?? 'null'));
        }
    }
    // TODO: Implement confirm dialog [NL]
    async #deleteGroup(groupKey) {
        const groupName = this.#blockGroups?.find((group) => group.key === groupKey)?.name ?? '';
        await umbConfirmModal(this, {
            headline: '#blockEditor_confirmDeleteBlockGroupTitle',
            content: this.localize.term('blockEditor_confirmDeleteBlockGroupMessage', [groupName]),
            color: 'danger',
            confirmLabel: '#general_delete',
        });
        // If a group is deleted, Move the blocks to no group:
        this.value = this.#value.map((block) => (block.groupKey === groupKey ? { ...block, groupKey: undefined } : block));
        if (this.#blockGroups) {
            this.#updateBlockGroupsValue(this.#blockGroups.filter((group) => group.key !== groupKey));
        }
    }
    #onGroupNameChange(e, groupKey) {
        const groupName = e.target.value;
        // TODO: make one method for updating the blockGroupsDataSetValue: [NL]
        this.#datasetContext?.setPropertyValue('blockGroups', this.#blockGroups?.map((group) => (group.key === groupKey ? { ...group, name: groupName } : group)));
    }
    render() {
        return html `<div id="groups">
			${this._notGroupedBlockTypes
            ? html `<umb-input-block-type
						.propertyAlias=${this._alias}
						.value=${this._notGroupedBlockTypes}
						.workspacePath=${this._workspacePath}
						@change=${(e) => this.#onChange(e, undefined)}
						@create=${(e) => this.#onCreate(e, undefined)}></umb-input-block-type>`
            : ''}
			${repeat(this._groupsWithBlockTypes, (group) => group.key, (group) => html `<div class="group" data-umb-group-key=${ifDefined(group.key)}>
						${group.key ? this.#renderGroupInput(group.key, group.name) : nothing}
						<umb-input-block-type
							data-umb-group-key=${group.key}
							.propertyAlias=${this._alias + '_' + group.key}
							.value=${group.blocks}
							.workspacePath=${this._workspacePath}
							@change=${(e) => this.#onChange(e, group.key)}
							@create=${(e) => this.#onCreate(e, group.key)}></umb-input-block-type>
					</div>`)}
		</div>`;
    }
    #renderGroupInput(groupKey, groupName) {
        return html `<div class="group-handle">
			<uui-icon name="icon-grip"></uui-icon>
			<uui-input
				label="Group"
				.value=${groupName ?? ''}
				@change=${(e) => this.#onGroupNameChange(e, groupKey)}>
			</uui-input>
			<uui-button
				compact
				label=${this.localize.term('general_delete')}
				look="outline"
				@click=${() => this.#deleteGroup(groupKey)}>
				<uui-icon name="icon-trash"></uui-icon>
			</uui-button>
		</div>`;
    }
    static { this.styles = [
        UmbTextStyles,
        css `
			.group-handle {
				display: flex;
				align-items: center;
				padding: var(--uui-size-3) var(--uui-size-1);
				margin-top: var(--uui-size-6);
				margin-bottom: var(--uui-size-4);
				gap: var(--uui-size-1);
				cursor: grab;
			}

			.group-handle:active {
				cursor: grabbing;
			}

			.group-handle:hover {
				background-color: var(--uui-color-divider);
				border-radius: var(--uui-border-radius);
			}

			.group:has([drag-placeholder]) {
				opacity: 0.2;
			}

			uui-input {
				flex: 1;
			}
		`,
    ]; }
};
__decorate([
    property({ attribute: false })
], UmbPropertyEditorUIBlockGridTypeConfigurationElement.prototype, "value", null);
__decorate([
    state()
], UmbPropertyEditorUIBlockGridTypeConfigurationElement.prototype, "_alias", void 0);
__decorate([
    property({ type: Object, attribute: false })
], UmbPropertyEditorUIBlockGridTypeConfigurationElement.prototype, "config", void 0);
__decorate([
    state()
], UmbPropertyEditorUIBlockGridTypeConfigurationElement.prototype, "_groupsWithBlockTypes", void 0);
__decorate([
    state()
], UmbPropertyEditorUIBlockGridTypeConfigurationElement.prototype, "_notGroupedBlockTypes", void 0);
__decorate([
    state()
], UmbPropertyEditorUIBlockGridTypeConfigurationElement.prototype, "_workspacePath", void 0);
UmbPropertyEditorUIBlockGridTypeConfigurationElement = __decorate([
    customElement('umb-property-editor-ui-block-grid-type-configuration')
], UmbPropertyEditorUIBlockGridTypeConfigurationElement);
export { UmbPropertyEditorUIBlockGridTypeConfigurationElement };
export default UmbPropertyEditorUIBlockGridTypeConfigurationElement;
