/* eslint-disable @typescript-eslint/naming-convention */
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;
};
var __metadata = (this && this.__metadata) || function (k, v) {
    if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
// #region Imports
import { HTMLElementEventEmitter } from '@breadstone/mosaik-elements';
import { Emit } from '../../events/Decorators/EmitDecorator';
import { Attribute } from '../Decorators/AttributeDecorator';
/**
 * @public
 */
export var IExpandableProps;
(function (IExpandableProps) {
    IExpandableProps.DEFAULTS = {
        isExpanded: false
    };
})(IExpandableProps || (IExpandableProps = {}));
/**
 * A mixin that provides expand/collapse functionality to a custom element.
 *
 * @fires expanded {ExpandedEvent} - Fired when the element is expanded.
 * @fires collapsed {CollapsedEvent} - Fired when the element is collapsed.
 * @fires toggled {ToggledEvent} - Fired when the element is toggled.
 *
 * @public
 */
export const Expandable = (base) => {
    class ExpandableElement extends base {
        // #region Fields
        _expanded;
        _collapsed;
        _toggled;
        _isExpanded;
        // #endregion
        // #region Ctor
        /**
         * Constructs a new instance of the `ExpandableElement` class.
         *
         * @public
         */
        constructor(...args) {
            super(...args);
            this._expanded = new HTMLElementEventEmitter(this, 'expanded');
            this._collapsed = new HTMLElementEventEmitter(this, 'collapsed');
            this._toggled = new HTMLElementEventEmitter(this, 'toggled');
            this._isExpanded = IExpandableProps.DEFAULTS.isExpanded;
        }
        // #endregion
        // #region Properties
        /**
         * Gets or sets the `isExpanded` property.
         * The default value is `false`, which means the element is collapsed.
         *
         * @public
         * @attr
         */
        get isExpanded() {
            return this._isExpanded;
        }
        set isExpanded(value) {
            if (this.disabled) {
                return;
            }
            if (this._isExpanded !== value) {
                this.onIsExpandedChanged(this._isExpanded, value);
            }
        }
        /**
         * Called when the element is expanded.
         * Provides reference to the `IEventDetail` as event argument.
         *
         * @public
         * @eventProperty
         * @readonly
         */
        get expanded() {
            return this._expanded;
        }
        /**
         * Called when the element is collapsed.
         * Provides reference to the `IEventDetail` as event argument.
         *
         * @public
         * @eventProperty
         * @readonly
         */
        get collapsed() {
            return this._collapsed;
        }
        /**
         * Called when the element is toggled.
         * Provides reference to the `IEventDetail` as event argument.
         *
         * @public
         * @eventProperty
         * @readonly
         */
        get toggled() {
            return this._toggled;
        }
        // #endregion
        // #region Methods
        /**
         * Expands the element.
         *
         * @public
         */
        expand() {
            if (this.disabled) {
                return;
            }
            if (this._isExpanded) {
                return;
            }
            this.isExpanded = true;
        }
        /**
         * Collapses the element.
         *
         * @public
         */
        collapse() {
            if (this.disabled) {
                return;
            }
            if (!this._isExpanded) {
                return;
            }
            this.isExpanded = false;
        }
        /**
         * Toggles the element between expanded and collapsed states.
         *
         * @public
         */
        toggle() {
            if (this.disabled) {
                return;
            }
            if (!this.isExpanded) {
                this.expand();
            }
            else {
                this.collapse();
            }
        }
        /**
         * Emits the {@link expanded} event.
         *
         * @protected
         */
        onExpanded(args) {
            this._expanded.emit(args);
        }
        /**
         * Emits the {@link collapsed} event.
         *
         * @protected
         */
        onCollapsed(args) {
            this._collapsed.emit(args);
        }
        /**
         * Emits the {@link toggled} event.
         *
         * @protected
         */
        onToggled(args) {
            this._toggled.emit(args);
        }
        /**
         * This method is invoked when the `isExpanded` property is changed.
         * Override this method to add custom behavior when the expanded state changes.
         *
         * @param prev - The previous value of `isExpanded`.
         * @param next - The new value of `isExpanded`.
         * @public
         */
        onIsExpandedChanged(prev, next) {
            if (prev === next) {
                return;
            }
            this._isExpanded = next;
            this.requestUpdate('isExpanded');
            if (next) {
                this.onExpanded({});
                this.onToggled({});
            }
            else {
                this.onCollapsed({});
                this.onToggled({});
            }
        }
    }
    __decorate([
        Emit({ eventName: 'expanded' }),
        __metadata("design:type", Object)
    ], ExpandableElement.prototype, "_expanded", void 0);
    __decorate([
        Emit({ eventName: 'collapsed' }),
        __metadata("design:type", Object)
    ], ExpandableElement.prototype, "_collapsed", void 0);
    __decorate([
        Emit({ eventName: 'toggled' }),
        __metadata("design:type", Object)
    ], ExpandableElement.prototype, "_toggled", void 0);
    __decorate([
        Attribute({
            type: Boolean,
            useDefault: true
        }),
        __metadata("design:type", Boolean),
        __metadata("design:paramtypes", [Boolean])
    ], ExpandableElement.prototype, "isExpanded", null);
    __decorate([
        Emit(),
        __metadata("design:type", Object),
        __metadata("design:paramtypes", [])
    ], ExpandableElement.prototype, "expanded", null);
    __decorate([
        Emit(),
        __metadata("design:type", Object),
        __metadata("design:paramtypes", [])
    ], ExpandableElement.prototype, "collapsed", null);
    __decorate([
        Emit(),
        __metadata("design:type", Object),
        __metadata("design:paramtypes", [])
    ], ExpandableElement.prototype, "toggled", null);
    return ExpandableElement;
};
//# sourceMappingURL=Expandable.js.map