import {memo, PropsWithChildren, useCallback} from 'react';
import {
  NativeSyntheticEvent,
  requireNativeComponent,
  StyleProp,
  ViewProps,
  ViewStyle,
} from 'react-native';

/**
 * Currently iOS ONLY !!!
 * This Native component is a wrapper around a native view that detects double tap and long press gestures
 * and provides the coordinates of the gesture.
 * =========
 * Is useful instead of using RNGH, with RNGH to cancel any RN pressable we need to use GestureDetector or they will be triggered together
 * this component solves this problem
 */

type Point = {
  x: number;
  y: number;
  absoluteX: number;
  absoluteY: number;
};

type Event = NativeSyntheticEvent<Point>;

interface NativePressableProps extends ViewProps {
  withHaptic?: boolean;
  /**
   * Offset from the left to ignore the gesture
   */
  gestureOffsetLeft?: number;
  /**
   * Offset from the right to ignore the gesture
   */
  gestureOffsetRight?: number;
  onDoubleTapCallback?: (e: Event) => void;
  onLongPressCallback?: (e: Event) => void;
}

const COMPONENT_NAME = 'RNGesturePressableView';

const RNGesturePressableViewComponent =
  requireNativeComponent<NativePressableProps>(COMPONENT_NAME);

export interface RNGesturePressableProps
  extends PropsWithChildren,
    Pick<
      NativePressableProps,
      'withHaptic' | 'gestureOffsetLeft' | 'gestureOffsetRight'
    > {
  style?: StyleProp<ViewStyle>;
  onDoubleTap?: (e: Point) => void;
  onLongPress?: (e: Point) => void;
}

const RNGesturePressableComponent = ({
  children,
  onDoubleTap,
  onLongPress,
  ...props
}: RNGesturePressableProps) => {
  const handleDoubleTap = useCallback(
    (e: Event) => {
      if (onDoubleTap) {
        onDoubleTap({
          x: e.nativeEvent.x,
          y: e.nativeEvent.y,
          absoluteX: e.nativeEvent.absoluteX,
          absoluteY: e.nativeEvent.absoluteY,
        });
      }
    },
    [onDoubleTap],
  );

  const handleLongPress = useCallback(
    (e: Event) => {
      if (onLongPress) {
        onLongPress({
          x: e.nativeEvent.x,
          y: e.nativeEvent.y,
          absoluteX: e.nativeEvent.absoluteX,
          absoluteY: e.nativeEvent.absoluteY,
        });
      }
    },
    [onLongPress],
  );

  return (
    <RNGesturePressableViewComponent
      {...props}
      onDoubleTapCallback={handleDoubleTap}
      onLongPressCallback={handleLongPress}>
      {children}
    </RNGesturePressableViewComponent>
  );
};

export const RNGesturePressable = memo(RNGesturePressableComponent);

export {default as RNGesturePressableNoDoubleTap} from './RNGesturePressableNoDoubleTap';
