import { __esDecorate, __runInitializers } from "tslib";
import { LitElement } from 'lit';
import { property } from 'lit/decorators.js';
import { fromError } from '../../exceptions/builder.js';
/**
 * Base class for modeling elements
 *
 * @fires change - When something changed
 * @fires error - When an error occurred. The event detail will contain an Exception object.
 */
let ModelingElement = (() => {
    let _classSuper = LitElement;
    let _root_decorators;
    let _root_initializers = [];
    let _root_extraInitializers = [];
    let _namespace_decorators;
    let _namespace_initializers = [];
    let _namespace_extraInitializers = [];
    let _selected_decorators;
    let _selected_initializers = [];
    let _selected_extraInitializers = [];
    let _readOnly_decorators;
    let _readOnly_initializers = [];
    let _readOnly_extraInitializers = [];
    return class ModelingElement extends _classSuper {
        static {
            const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
            _root_decorators = [property({ type: Object })];
            _namespace_decorators = [property({ type: String })];
            _selected_decorators = [property({ type: String })];
            _readOnly_decorators = [property({ type: Boolean })];
            __esDecorate(this, null, _root_decorators, { kind: "accessor", name: "root", static: false, private: false, access: { has: obj => "root" in obj, get: obj => obj.root, set: (obj, value) => { obj.root = value; } }, metadata: _metadata }, _root_initializers, _root_extraInitializers);
            __esDecorate(this, null, _namespace_decorators, { kind: "accessor", name: "namespace", static: false, private: false, access: { has: obj => "namespace" in obj, get: obj => obj.namespace, set: (obj, value) => { obj.namespace = value; } }, metadata: _metadata }, _namespace_initializers, _namespace_extraInitializers);
            __esDecorate(this, null, _selected_decorators, { kind: "accessor", name: "selected", static: false, private: false, access: { has: obj => "selected" in obj, get: obj => obj.selected, set: (obj, value) => { obj.selected = value; } }, metadata: _metadata }, _selected_initializers, _selected_extraInitializers);
            __esDecorate(this, null, _readOnly_decorators, { kind: "accessor", name: "readOnly", static: false, private: false, access: { has: obj => "readOnly" in obj, get: obj => obj.readOnly, set: (obj, value) => { obj.readOnly = value; } }, metadata: _metadata }, _readOnly_initializers, _readOnly_extraInitializers);
            if (_metadata) Object.defineProperty(this, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
        }
        #root_accessor_storage = __runInitializers(this, _root_initializers, void 0);
        /**
         * The instance of the root DataNamespace.
         */
        get root() { return this.#root_accessor_storage; }
        set root(value) { this.#root_accessor_storage = value; }
        #namespace_accessor_storage = (__runInitializers(this, _root_extraInitializers), __runInitializers(this, _namespace_initializers, void 0));
        /**
         * The parent namespace this element belongs to.
         * When rendering a foreign domain, this will be the namespace of the foreign domain.
         * Normally, this is the `key` of the root DataDomain.
         */
        get namespace() { return this.#namespace_accessor_storage; }
        set namespace(value) { this.#namespace_accessor_storage = value; }
        #selected_accessor_storage = (__runInitializers(this, _namespace_extraInitializers), __runInitializers(this, _selected_initializers, void 0));
        /**
         * The selected object that this element is interested in.
         * @attribute
         */
        get selected() { return this.#selected_accessor_storage; }
        set selected(value) { this.#selected_accessor_storage = value; }
        #readOnly_accessor_storage = (__runInitializers(this, _selected_extraInitializers), __runInitializers(this, _readOnly_initializers, void 0));
        /**
         * If true, the element is in read-only mode.
         * This means that the element will not allow any modifications to the data.
         * @attribute
         */
        get readOnly() { return this.#readOnly_accessor_storage; }
        set readOnly(value) { this.#readOnly_accessor_storage = value; }
        /**
         * Computed property that indicates if the element is a foreign element.
         * A foreign element is one that is not part of the root DataDomain.
         */
        get isForeignElement() {
            return this.root !== undefined && this.namespace !== this.root.key;
        }
        /**
         * Computed property that indicates if the element can be edited.
         * An element can be edited if it is not read-only and is not a foreign element.
         */
        get canEdit() {
            return !this.readOnly && !this.isForeignElement;
        }
        constructor() {
            super();
            __runInitializers(this, _readOnly_extraInitializers);
            this.handleDomainChange = this.handleDomainChange.bind(this);
        }
        willUpdate(cp) {
            if (cp.has('root')) {
                const old = cp.get('root');
                if (old) {
                    old.removeEventListener('change', this.handleDomainChange);
                }
                this.root?.addEventListener('change', this.handleDomainChange);
            }
            super.willUpdate(cp);
        }
        handleDomainChange() {
            this.requestUpdate();
        }
        /**
         * A common way for an element to notify a change.
         */
        notifyChange() {
            this.dispatchEvent(new Event('change'));
        }
        /**
         * Reports an error to the element.
         * It will dispatch an 'error' event with the Exception object as the detail.
         * It unifies the error handling across the application.
         * @param error The error to report.
         */
        reportError(error) {
            const e = fromError(error);
            this.dispatchEvent(new CustomEvent('error', {
                bubbles: true,
                composed: true,
                detail: e,
            }));
        }
    };
})();
export { ModelingElement };
//# sourceMappingURL=ModelingElement.js.map