import { html } from 'lit';
import { queryAsync, property } from 'lit/decorators.js';
import FlowRdfElement from '../../internal/flow-ui-rdf-element.mjs';
import { watch } from '../../internal/watch.mjs';
import componentStyles from '../../styles/component.styles.mjs';
import styles from './animation.styles.mjs';
import * as index from '../../internal/animations/index.mjs';
import { easings } from '../../internal/animations/easings/easings.mjs';

var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __decorateClass = (decorators, target, key, kind) => {
  var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
  for (var i = decorators.length - 1, decorator; i >= 0; i--)
    if (decorator = decorators[i])
      result = (kind ? decorator(target, key, result) : decorator(result)) || result;
  if (kind && result)
    __defProp(target, key, result);
  return result;
};
class FlowUiAnimation extends FlowRdfElement {
  constructor() {
    super(...arguments);
    this.hasStarted = false;
    this.name = "none";
    this.play = false;
    this.delay = 0;
    this.direction = "normal";
    this.duration = 1e3;
    this.easing = "linear";
    this.endDelay = 0;
    this.fill = "auto";
    this.iterations = Infinity;
    this.iterationStart = 0;
    this.playbackRate = 1;
    this.handleAnimationFinish = () => {
      this.play = false;
      this.hasStarted = false;
      this.emit("flow-ui-finish");
    };
    this.handleAnimationCancel = () => {
      this.play = false;
      this.hasStarted = false;
      this.emit("flow-ui-cancel");
    };
  }
  /** Gets and sets the current animation time. */
  get currentTime() {
    return this.animation?.currentTime ?? 0;
  }
  set currentTime(time) {
    if (this.animation) {
      this.animation.currentTime = time;
    }
  }
  connectedCallback() {
    super.connectedCallback();
    this.createAnimation();
  }
  disconnectedCallback() {
    super.disconnectedCallback();
    this.destroyAnimation();
  }
  handleSlotChange() {
    this.destroyAnimation();
    this.createAnimation();
  }
  async createAnimation() {
    const easing = easings[this.easing] ?? this.easing;
    const keyframes = this.keyframes ?? index[this.name];
    const slot = await this.defaultSlot;
    const element = slot.assignedElements()[0];
    if (!element || !keyframes) {
      return false;
    }
    this.destroyAnimation();
    this.animation = element.animate(keyframes, {
      delay: +this.delay,
      direction: this.direction,
      duration: this.duration,
      easing,
      endDelay: this.endDelay,
      fill: this.fill,
      iterationStart: this.iterationStart,
      iterations: this.iterations
    });
    this.animation.playbackRate = this.playbackRate;
    this.animation.addEventListener("cancel", this.handleAnimationCancel);
    this.animation.addEventListener("finish", this.handleAnimationFinish);
    if (this.play) {
      this.hasStarted = true;
      this.emit("flow-ui-start");
    } else {
      this.animation.pause();
    }
    return true;
  }
  destroyAnimation() {
    if (this.animation) {
      this.animation.cancel();
      this.animation.removeEventListener("cancel", this.handleAnimationCancel);
      this.animation.removeEventListener("finish", this.handleAnimationFinish);
      this.hasStarted = false;
    }
  }
  handleAnimationChange() {
    if (!this.hasUpdated) {
      return;
    }
    this.createAnimation();
  }
  handlePlayChange() {
    if (this.animation) {
      if (this.play && !this.hasStarted) {
        this.hasStarted = true;
        this.emit("flow-ui-start");
      }
      if (this.play) {
        this.animation.play();
      } else {
        this.animation.pause();
      }
      return true;
    }
    return false;
  }
  handlePlaybackRateChange() {
    if (this.animation) {
      this.animation.playbackRate = this.playbackRate;
    }
  }
  /** Clears all keyframe effects caused by this animation and aborts its playback. */
  cancel() {
    this.animation?.cancel();
  }
  /** Sets the playback time to the end of the animation corresponding to the current playback direction. */
  finish() {
    this.animation?.finish();
  }
  render() {
    return html`
      <slot @slotchange=${this.handleSlotChange}></slot>
    `;
  }
}
FlowUiAnimation.styles = [componentStyles, styles];
__decorateClass([
  queryAsync("slot")
], FlowUiAnimation.prototype, "defaultSlot", 2);
__decorateClass([
  property()
], FlowUiAnimation.prototype, "name", 2);
__decorateClass([
  property({ type: Boolean, reflect: true })
], FlowUiAnimation.prototype, "play", 2);
__decorateClass([
  property({ type: Number })
], FlowUiAnimation.prototype, "delay", 2);
__decorateClass([
  property()
], FlowUiAnimation.prototype, "direction", 2);
__decorateClass([
  property({ type: Number })
], FlowUiAnimation.prototype, "duration", 2);
__decorateClass([
  property()
], FlowUiAnimation.prototype, "easing", 2);
__decorateClass([
  property({ attribute: "end-delay", type: Number })
], FlowUiAnimation.prototype, "endDelay", 2);
__decorateClass([
  property()
], FlowUiAnimation.prototype, "fill", 2);
__decorateClass([
  property({ type: Number })
], FlowUiAnimation.prototype, "iterations", 2);
__decorateClass([
  property({ attribute: "iteration-start", type: Number })
], FlowUiAnimation.prototype, "iterationStart", 2);
__decorateClass([
  property({ attribute: false })
], FlowUiAnimation.prototype, "keyframes", 2);
__decorateClass([
  property({ attribute: "playback-rate", type: Number })
], FlowUiAnimation.prototype, "playbackRate", 2);
__decorateClass([
  watch([
    "name",
    "delay",
    "direction",
    "duration",
    "easing",
    "endDelay",
    "fill",
    "iterations",
    "iterationsStart",
    "keyframes"
  ])
], FlowUiAnimation.prototype, "handleAnimationChange", 1);
__decorateClass([
  watch("play")
], FlowUiAnimation.prototype, "handlePlayChange", 1);
__decorateClass([
  watch("playbackRate")
], FlowUiAnimation.prototype, "handlePlaybackRateChange", 1);

export { FlowUiAnimation as default };
