import Button from '@components/Button'
import { StyleConstants } from '@utils/styles/constants'
import { ResizeMode, Video, VideoFullscreenUpdate } from 'expo-av'
import React, { useCallback, useEffect, useRef, useState } from 'react'
import { AppState, AppStateStatus, Pressable, View } from 'react-native'
import { Blurhash } from 'react-native-blurhash'
import attachmentAspectRatio from './aspectRatio'
import AttachmentAltText from './AltText'
import { Platform } from 'expo-modules-core'

export interface Props {
  total: number
  index: number
  sensitiveShown: boolean
  video: Mastodon.AttachmentVideo | Mastodon.AttachmentGifv
  gifv?: boolean
}

const AttachmentVideo: React.FC<Props> = ({
  total,
  index,
  sensitiveShown,
  video,
  gifv = false
}) => {
  const videoPlayer = useRef<Video>(null)
  const [videoLoading, setVideoLoading] = useState(false)
  const [videoLoaded, setVideoLoaded] = useState(false)
  const [videoPosition, setVideoPosition] = useState<number>(0)
  const [videoResizeMode, setVideoResizeMode] = useState<ResizeMode>(ResizeMode.COVER)
  const playOnPress = useCallback(async () => {
    setVideoLoading(true)
    if (!videoLoaded) {
      await videoPlayer.current?.loadAsync({ uri: video.url })
    }
    Platform.OS === 'android' && setVideoResizeMode(ResizeMode.CONTAIN)
    await videoPlayer.current?.setPositionAsync(videoPosition)
    await videoPlayer.current?.presentFullscreenPlayer()
    videoPlayer.current?.playAsync()
    setVideoLoading(false)
    videoPlayer.current?.setOnPlaybackStatusUpdate(props => {
      if (props.isLoaded) {
        setVideoLoaded(true)
        if (props.positionMillis) {
          setVideoPosition(props.positionMillis)
        }
      }
    })
  }, [videoLoaded, videoPosition])

  const appState = useRef(AppState.currentState)
  useEffect(() => {
    const appState = AppState.addEventListener('change', _handleAppStateChange)

    return () => appState.remove()
  }, [])
  const _handleAppStateChange = async (nextAppState: AppStateStatus) => {
    if (appState.current.match(/active/) && nextAppState.match(/inactive/)) {
      // await videoPlayer.current?.stopAsync()
    } else if (gifv && appState.current.match(/background/) && nextAppState.match(/active/)) {
      await videoPlayer.current?.setIsMutedAsync(true)
      await videoPlayer.current?.playAsync()
    }

    appState.current = nextAppState
  }

  const playerStatus = useRef<any>(null)
  useEffect(() => {
    videoPlayer.current?.setOnPlaybackStatusUpdate(playbackStatus => {
      playerStatus.current = playbackStatus
    })
  }, [])

  return (
    <View
      style={{
        flex: 1,
        flexBasis: '50%',
        padding: StyleConstants.Spacing.XS / 2,
        aspectRatio: attachmentAspectRatio({ total, index })
      }}
    >
      <Video
        accessibilityLabel={video.description}
        ref={videoPlayer}
        style={{
          width: '100%',
          height: '100%',
          opacity: sensitiveShown ? 0 : 1
        }}
        usePoster
        resizeMode={videoResizeMode}
        {...(gifv
          ? {
              shouldPlay: true,
              isMuted: true,
              isLooping: true,
              source: { uri: video.url }
            }
          : {
              posterSource: { uri: video.preview_url },
              posterStyle: { resizeMode: ResizeMode.COVER }
            })}
        useNativeControls={false}
        onFullscreenUpdate={async event => {
          if (event.fullscreenUpdate === VideoFullscreenUpdate.PLAYER_DID_DISMISS) {
            Platform.OS === 'android' && setVideoResizeMode(ResizeMode.COVER)
            if (!gifv) {
              await videoPlayer.current?.pauseAsync()
            }
          }
        }}
      />
      <Pressable
        style={{
          position: 'absolute',
          width: '100%',
          height: '100%',
          flex: 1,
          justifyContent: 'center',
          alignItems: 'center'
        }}
        onPress={gifv ? playOnPress : null}
      >
        {sensitiveShown ? (
          video.blurhash ? (
            <Blurhash
              blurhash={video.blurhash}
              style={{
                width: '100%',
                height: '100%'
              }}
            />
          ) : null
        ) : !gifv || (gifv && playerStatus.current === false) ? (
          <Button
            round
            overlay
            size='L'
            type='icon'
            content='PlayCircle'
            onPress={playOnPress}
            loading={videoLoading}
          />
        ) : null}
        <AttachmentAltText sensitiveShown={sensitiveShown} text={video.description} />
      </Pressable>
    </View>
  )
}

export default AttachmentVideo
