import React, {ReactNode, useState} from 'react';
import {LayoutChangeEvent, StyleProp, ViewStyle} from 'react-native';
import {
  Gesture,
  GestureDetector,
  GestureHandlerRootView,
} from 'react-native-gesture-handler';
import Animated, {
  useSharedValue,
  useAnimatedStyle,
  withTiming,
} from 'react-native-reanimated';
import {windowDimensions} from '@shared/constants';

import {styles} from './styles';

export interface AndroidZoomProps {
  children: ReactNode;
  style?: StyleProp<ViewStyle>;
  doubleTapZoom?: boolean;
}

function AndroidZoom({
  children,
  style,
  doubleTapZoom = true,
}: AndroidZoomProps) {
  const [layout, setLayout] = useState({
    width: windowDimensions.width,
    height: windowDimensions.height,
  });
  const scale = useSharedValue(1);
  const focalX = useSharedValue(0);
  const focalY = useSharedValue(0);

  const pinchGesture = Gesture.Pinch()
    .onUpdate(e => {
      if (e.scale > 0.6) {
        scale.value = e.scale;
        focalX.value = e.focalX;
        focalY.value = e.focalY;
      }
    })
    .onEnd(() => {
      scale.value = withTiming(1);
    });

  const doubleTapGesture = Gesture.Tap()
    .numberOfTaps(2)
    .maxDelay(100)
    .onEnd(e => {
      scale.value = scale.value * 1.5;
      focalX.value = e.absoluteX;
      focalY.value = e.absoluteY;
    });

  const animatedStyle = useAnimatedStyle(() => ({
    transform: [
      {translateX: focalX.value},
      {translateY: focalY.value},
      {translateX: -layout.width / 2},
      {translateY: -layout.height / 2},
      {scale: scale.value},
      {translateX: -focalX.value},
      {translateY: -focalY.value},
      {translateX: layout.width / 2},
      {translateY: layout.height / 2},
    ],
  }));

  const composedGestures = doubleTapZoom
    ? Gesture.Exclusive(doubleTapGesture, pinchGesture)
    : Gesture.Exclusive(pinchGesture);

  const handleLayout = (event: LayoutChangeEvent) => {
    setLayout({
      width: event.nativeEvent.layout.width,
      height: event.nativeEvent.layout.height,
    });
  };

  return (
    <GestureHandlerRootView style={[styles.flex, style]}>
      <GestureDetector gesture={composedGestures}>
        <Animated.View
          style={[styles.flex, animatedStyle]}
          onLayout={handleLayout}>
          {children}
        </Animated.View>
      </GestureDetector>
    </GestureHandlerRootView>
  );
}

export default AndroidZoom;
