import { html, LitElement } from 'lit';
import { customElement, property, state } from 'lit/decorators.js';
import { ifDefined } from 'lit/directives/if-defined.js';
import { createRef, ref } from 'lit/directives/ref.js';
import { styleMap } from 'lit/directives/style-map.js';

import type { DialogEmbedProps } from '.';
import type { MediaPlayer } from '@vouchfor/media-player';

import './DialogOverlay';

@customElement('vouch-embed-dialog-portal')
class DialogPortal extends LitElement {
  @property({ type: String }) vouchId: DialogEmbedProps['vouchId'];
  @property({ type: String }) templateId: DialogEmbedProps['templateId'];
  @property({ type: Array }) questions: DialogEmbedProps['questions'];

  @property({ type: String }) env: DialogEmbedProps['env'] = 'prod';
  @property({ type: String }) apiKey: DialogEmbedProps['apiKey'] = '';
  @property({ type: Boolean }) disableTracking: DialogEmbedProps['disableTracking'] = false;
  @property({ type: String }) trackingSource: DialogEmbedProps['trackingSource'] = 'embedded_player';

  @property({ type: Array }) controls: DialogEmbedProps['controls'];
  @property({ type: String }) preload: DialogEmbedProps['preload'] = 'none';
  @property({ type: Boolean }) disableAutoplay: DialogEmbedProps['disableAutoplay'] = false;
  @property({ type: Number }) aspectRatio: DialogEmbedProps['aspectRatio'] = 0;

  private _mediaPlayerRef = createRef<MediaPlayer>();

  @state() open = false;

  private _handleToggle = ({ detail }: CustomEvent<string>) => {
    // Because we have to attach this listener to the document since this element is portalled outside of the button,
    // we also have to make sure that this player is actually the one we want to open and play by passing in an ID
    // from the button wrapper parent and checking against that same ID we pass as the event detail
    if (this.id === detail) {
      this.open = !this.open;

      if (this.open) {
        if (!this.disableAutoplay && this._mediaPlayerRef?.value) {
          this._mediaPlayerRef.value.muted = false;
          this._mediaPlayerRef.value.play();
        }
      } else {
        this._mediaPlayerRef?.value?.pause();
      }
    }
  };

  // We could do the same thing on close and check for the correct ID but it doesn't really matter
  private _handleClose = () => {
    this.open = false;
    this._mediaPlayerRef?.value?.pause();
  };

  private _handleDocumentKeyUp = (e: KeyboardEvent) => {
    if (e.key === 'Escape') {
      this._handleClose();
    }
  };

  connectedCallback(): void {
    super.connectedCallback();
    document.addEventListener('dialogembed:click', this._handleToggle);
    document.addEventListener('keyup', this._handleDocumentKeyUp);
    document.addEventListener('close:click', this._handleClose);
    document.addEventListener('overlay:click', this._handleClose);
  }

  disconnectedCallback(): void {
    super.disconnectedCallback();
    document.removeEventListener('dialogembed:click', this._handleToggle);
    document.removeEventListener('keyup', this._handleDocumentKeyUp);
    document.removeEventListener('close:click', this._handleClose);
    document.removeEventListener('overlay:click', this._handleClose);
  }

  protected createRenderRoot(): HTMLElement | DocumentFragment {
    // We must create a new node here because portalling into the same node (document.body) causes the second
    // element to overwrite the first for some reason (not behaviour really stated in the docs)
    // I am fairly certain this function is only run once as the default behaviour creates the open shadow root
    // and returns that shadow root in this function: https://lit.dev/docs/components/shadow-dom/#implementing-createrenderroot
    const newNode = document.createElement('div');
    document.body.appendChild(newNode);
    return newNode;
  }

  render() {
    return html`
      <vouch-embed-dialog-overlay ?open=${this.open} aspectRatio=${this.aspectRatio}>
        <vouch-embed-player
          ${ref(this._mediaPlayerRef)}
          style=${styleMap({
            maxWidth: '100%',
            maxHeight: '100%'
          })}
          ?autoplay=${false}
          vouchId=${ifDefined(this.vouchId)}
          templateId=${ifDefined(this.templateId)}
          .questions=${this.questions}
          .controls=${this.controls}
          env=${ifDefined(this.env)}
          apiKey=${ifDefined(this.apiKey)}
          ?disableTracking=${this.disableTracking}
          trackingSource=${ifDefined(this.trackingSource)}
          preload=${ifDefined(this.preload)}
          aspectRatio=${this.aspectRatio}
        ></vouch-embed-player>
      </vouch-embed-dialog-overlay>
    `;
  }
}

declare global {
  interface HTMLElementTagNameMap {
    'vouch-embed-dialog-portal': DialogPortal;
  }

  namespace JSX {
    interface IntrinsicElements {
      'vouch-embed-dialog-portal': DialogPortal;
    }
  }
}

export { DialogPortal };
