/* 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 { AnimationPlayer } from '../../Animations/AnimationPlayer';
import { Property } from '../Decorators/PropertyDecorator';
/**
 * @public
 */
export const Animatable = (base) => {
    class AnimatableElement extends base {
        // #region Fields
        _animationPlayer;
        _animationReady;
        _enter;
        _exit;
        _animationTarget;
        // #endregion
        // #region Ctor
        /**
         * Constructs a new instance of the `AnimatableElement` class.
         *
         * @public
         */
        constructor(...args) {
            super(args);
            this._animationReady = false;
            this._enter = IAnimatableProps.DEFAULTS.enter;
            this._exit = IAnimatableProps.DEFAULTS.exit;
            this._animationPlayer = null;
            this._animationTarget = null;
        }
        // #endregion
        // #region Properties
        /**
         * Gets the target element for animations.
         * Override this getter to animate a different element than the host (e.g., a template part).
         *
         * @public
         * @readonly
         */
        get animationTarget() {
            return this;
        }
        /**
         * Gets or sets the `enter` animation property.
         * The default value is `null`, which means no animation is applied.
         *
         * @public
         * @attr enter
         */
        get enter() {
            return this._enter;
        }
        set enter(value) {
            if (this._enter !== value) {
                this._enter = value;
                this.requestUpdate('enter');
            }
        }
        /**
         * Gets or sets the `exit` animation property.
         * The default value is `null`, which means no animation is applied.
         *
         * @public
         * @attr exit
         */
        get exit() {
            return this._exit;
        }
        set exit(value) {
            if (this._exit !== value) {
                this._exit = value;
                this.requestUpdate('exit');
            }
        }
        // #endregion
        // #region Methods
        /**
         * @public
         * @override
         */
        connectedCallback() {
            super.connectedCallback();
            if ('onEnterAnimation' in this) {
                void this.onEnterAnimation();
            }
        }
        /**
         * @public
         * @override
         */
        disconnectedCallback() {
            if ('onExitAnimation' in this) {
                void this.onExitAnimation().then(() => {
                    super.disconnectedCallback();
                });
            }
            else {
                super.disconnectedCallback();
            }
        }
        /**
         * @public
         * @override
         */
        async play(animation) {
            const player = this.getAnimationPlayer();
            const target = this.animationTarget;
            const [, event] = await Promise.all([
                player.stopAll(target),
                player.play(target, animation)
            ]);
            return event.type === 'finish';
        }
        /**
         * Gets or creates the animation player.
         *
         * @private
         */
        getAnimationPlayer() {
            if (!this._animationPlayer) {
                this._animationPlayer = new AnimationPlayer();
            }
            return this._animationPlayer;
        }
    }
    __decorate([
        Property({ type: Object }),
        __metadata("design:type", Object),
        __metadata("design:paramtypes", [Object])
    ], AnimatableElement.prototype, "enter", null);
    __decorate([
        Property({ type: Object }),
        __metadata("design:type", Object),
        __metadata("design:paramtypes", [Object])
    ], AnimatableElement.prototype, "exit", null);
    return AnimatableElement;
};
/**
 * @public
 */
export var IAnimatableProps;
(function (IAnimatableProps) {
    IAnimatableProps.DEFAULTS = {
        enter: null,
        exit: null
    };
})(IAnimatableProps || (IAnimatableProps = {}));
//# sourceMappingURL=Animatable.js.map