import type {ComponentProps, FunctionComponent} from 'react'
import {useState} from 'react'
import type {TapGesture} from 'react-native-gesture-handler'
import {Gesture, GestureDetector, GestureHandlerRootView} from 'react-native-gesture-handler'
import {Image, Modal, useWindowDimensions} from 'react-native'
import {useTheme} from '@react-navigation/core'
import {scheduleOnRN} from 'react-native-worklets'

interface ZoomedImageViewProps extends ComponentProps<typeof Image> {
  gesture: TapGesture
}

const ZoomedImageView: FunctionComponent<ZoomedImageViewProps> = ({gesture, ...imageProps}) => {
  const dimensions = useWindowDimensions()
  const theme = useTheme()

  return (
    <Modal>
      <GestureHandlerRootView style={[{backgroundColor: theme.colors.card}]}>
        <GestureDetector gesture={gesture}>
          <Image {...imageProps} style={[imageProps.style, {width: dimensions.width, height: dimensions.height}]} />
        </GestureDetector>
      </GestureHandlerRootView>
    </Modal>
  )
}

type ImageWithGestureProps = ComponentProps<typeof Image>

const ImageWithGestures: FunctionComponent<ImageWithGestureProps> = ({...imageProps}) => {
  const [isZoomed, setIsZoomed] = useState<boolean>(false)

  const toggleIsZoomed = () => setIsZoomed(x => !x)

  // Standaard worden callbacks vanuit de Gesture API uitgevoerd in de UI-thread, maar in dit geval willen we dat
  // de callback in de JS-thread uitgevoerd wordt omdat we de state willen aanpassen (en die bestaat enkel in het
  // UI-thread).
  // De scheduleOnRN neemt een callbackfunctie als argument die op het JS-thread uitgevoerd wordt.
  const doubleTap = Gesture.Tap()
    .numberOfTaps(2)
    .onEnd(() => scheduleOnRN(toggleIsZoomed))

  return (
    // Detecteer een gebaar, in dit geval een dubbel-tap.
    // Deze providers kunnen genest worden om meerdere gestures te detecteren.
    <GestureDetector gesture={doubleTap}>
      {isZoomed ? <ZoomedImageView {...imageProps} gesture={doubleTap} /> : <Image {...imageProps} />}
    </GestureDetector>
  )
}

export default ImageWithGestures
