// #region Imports
import { directive, PartType } from 'lit/directive.js';
import { DirectiveBase } from '../../Controls/Directives/Abstracts/DirectiveBase';
import { RendererServiceLocator } from '../../Dom/Renderer';
import { AnimationPlayer } from '../AnimationPlayer';
import { isAnimationRef } from './AnimationRefDirective';
// #endregion
/**
 * The `AnimateDirective` class.
 *
 * @public
 */
export class AnimateDirective extends DirectiveBase {
    // #region Fields
    _animationPlayer;
    _wasTriggered;
    _element;
    // #endregion
    // #region Ctor
    /**
     * Constructs a new instance of the `AnimateDirective` class.
     *
     * @public
     */
    constructor(args) {
        super(args);
        if (args.type !== PartType.ELEMENT) {
            throw new Error('The `animate` directive must be used in attribute position.');
        }
        this._wasTriggered = false;
        this._animationPlayer = new AnimationPlayer();
        this._element = null;
    }
    // #endregion
    // #region Methods
    /**
     * Renders the directive with the provided animation options.
     *
     * @param _optionsOrRef - The animation options or an animation reference.
     * @returns Empty string (actual work is done in update).
     * @public
     */
    render(_optionsOrRef) {
        return '';
    }
    /**
     * Updates the directive and triggers the animation.
     *
     * @param part - The element part containing the target element.
     * @param args - The directive arguments.
     * @returns The render result.
     * @public
     */
    update(part, [optionsOrRef]) {
        this._element = part.element;
        if (!this._wasTriggered) {
            this._wasTriggered = true;
            if (isAnimationRef(optionsOrRef)) {
                return this.render(optionsOrRef);
            }
            const animationOptions = optionsOrRef;
            // Apply initial styles immediately (synchronously)
            this.applyInitialStyles(animationOptions);
            // Only animate if there are steps defined
            if (animationOptions.steps && animationOptions.steps.length > 0) {
                if (animationOptions.trigger) {
                    animationOptions.trigger(() => {
                        this.playAnimation(animationOptions);
                    });
                }
                else {
                    // Play animation immediately - initial styles are already applied
                    this.playAnimation(animationOptions);
                }
            }
        }
        return this.render(optionsOrRef);
    }
    /**
     * Applies the initial styles to the element.
     *
     * @param options - The animation options containing the initial keyframe.
     * @private
     */
    applyInitialStyles(options) {
        if (!options.initial || !this._element) {
            return;
        }
        for (const [key, value] of Object.entries(options.initial)) {
            // Skip non-style keyframe properties
            if (key === 'offset' || key === 'easing' || key === 'composite') {
                continue;
            }
            if (key in this._element.style) {
                RendererServiceLocator.current.setStyle(this._element, key, value?.toString() ?? '');
            }
        }
    }
    /**
     * Plays the animation on the element.
     * Uses playToFinal to animate from current state (with initial styles) to the final keyframe.
     *
     * @param options - The animation options.
     * @private
     */
    playAnimation(options) {
        if (!this._element) {
            return;
        }
        void this._animationPlayer.playToFinal(this._element, options).then(() => {
            options.onFinished?.();
        });
    }
}
/**
 * A directive that triggers an animation on an element.
 *
 * @public
 */
export const animate = directive(AnimateDirective);
//# sourceMappingURL=AnimateDirective.js.map