import { createRef, ref } from 'lit/directives/ref.js';

import type { PlayerEmbed } from '..';
import type { ReactiveController, ReactiveControllerHost } from 'lit';
import type { DirectiveResult } from 'lit/directive.js';
import type { Ref } from 'lit/directives/ref.js';

import { forwardEvent } from '~/utils/events';

type PlayerEmbedHost = ReactiveControllerHost & PlayerEmbed;

class EventForwardController implements ReactiveController {
  host: PlayerEmbedHost;

  private _events: string[] = [];
  private _cleanup: (() => void)[] = [];
  private _forwardElementRef: Ref<HTMLElement> = createRef();

  constructor(host: PlayerEmbedHost, events: string[]) {
    this.host = host;
    this._events = events;
    host.addController(this);
  }

  register(): DirectiveResult {
    return ref(this._forwardElementRef);
  }

  hostConnected() {
    // Guaranteed to have the element ref in the RAF callback because of how the lit lifecycle works
    requestAnimationFrame(() => {
      this._events.forEach((event) => {
        if (this._forwardElementRef.value) {
          this._cleanup.push(forwardEvent(event, this._forwardElementRef.value, this.host));
        }
      });
    });
  }

  hostDisconnected() {
    this._cleanup.forEach((fn) => {
      fn();
    });
    this._cleanup = [];
  }
}

export { EventForwardController };
