import { useRef, useState } from 'preact/hooks'
import bubbleEvent from '../shared/bubble-event.js'
import getId from '../shared/get-id.js'
import getSizeClass from '../shared/get-size-class.js'
import h from '../shared/h.js'
import { MEDIA_PAUSE, MEDIA_PLAY } from '../shared/icons.js'
import t from '../shared/t.js'
import { Button } from './button.js'

export function Video ({ _model, _tall, _fit, ...props }) {
  const { src } = _model

  if (!src) {
    return null
  }

  const url = new URL(src, globalThis.origin)
  const Handler = globalThis.origin === url.origin ? HTMLVideo : EmbedVideo
  return h(Handler, { _model, _tall, _fit, ...props })
}

function EmbedVideo ({ _model, _tall, ...props }) {
  const { src, caption, autoplay } = _model
  const url = new URL(src)
  const sizeClass = getSizeClass(_tall)
  const [id] = useState(() => getId())

  // Support for YouTube background videos.
  const ytVideoId = src.replace(/https:\/\/(?:www\.)?(?:youtube\.com|youtube-nocookie\.com)\/embed\/([a-z0-9-_]{11})/i, '$1')

  // Enable JS API to allow postMessage control of the video for YouTube videos.
  url.searchParams.set('enablejsapi', 1)
  if (ytVideoId && autoplay) {
    url.searchParams.set('autoplay', 1)
    url.searchParams.set('playsinline', 1)
    url.searchParams.set('loop', 1)
    url.searchParams.set('mute', 1)
    url.searchParams.set('controls', 0)
    url.searchParams.set('playlist', ytVideoId)
  }

  // Iframe needs a default aspect ratio.
  return h('iframe', {
    ...props,
    id,
    className: `block aspect-video ${sizeClass}`,
    onLoad: bubbleEvent,
    loading: 'lazy',
    src: url.href,
    title: caption,
    allow: 'accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture',
    allowFullScreen: true
  })
}

// iOS is very particular about the videos:
// https://webkit.org/blog/6784/new-video-policies-for-ios/
function HTMLVideo ({ _model, _tall, _fit = 'cover', ...props }) {
  const { src, caption, autoplay } = _model

  const msgPause = t('Pause playback')
  const msgPlay = t('Resume playback')
  const sizeClass = getSizeClass(_tall)
  const fitClass = `object-${_fit}`
  const [state, setState] = useState({ icon: MEDIA_PAUSE, text: msgPause })
  const ref = useRef(null)

  return h('div', { ...props, className: `relative ${sizeClass}` },
    h('video', {
      ref,
      autoplay,
      className: `block ${sizeClass} ${fitClass}`,
      controls: !autoplay,
      title: caption,
      loop: autoplay,
      muted: autoplay, // https://stackoverflow.com/questions/61510160/why-muted-attribute-on-video-tag-is-ignored-in-react
      playsinline: autoplay,
      onTimeUpdate: bubbleEvent,
      children: h('source', { src })
    }),
    autoplay && h('div', { className: 'absolute top-4 end-4' },
      h(Button, {
        _variant: 'plain',
        _textless: true,
        _size: 'sm',
        _color: 'transparent',
        _model: { name: state.text, icon: state.icon },
        onClick: () => {
          if (ref.current.paused) {
            ref.current.play()
            setState({ icon: MEDIA_PAUSE, text: msgPause })
          } else {
            ref.current.pause()
            setState({ icon: MEDIA_PLAY, text: msgPlay })
          }
        }
      })
    )
  )
}
