/**
 * External dependencies
 */
import { Animated, PanResponder, StyleSheet, View } from 'react-native';
import Video from 'react-native-video';

/**
 * WordPress dependencies
 */
import { requestFocalPointPickerTooltipShown, setFocalPointPickerTooltipShown } from '@wordpress/react-native-bridge';
import { __ } from '@wordpress/i18n';
import { useRef, useState, useMemo, useEffect } from '@wordpress/element';
import { usePreferredColorSchemeStyle } from '@wordpress/compose';

/**
 * Internal dependencies
 */
import FocalPoint from './focal-point';
import Tooltip from './tooltip';
import styles from './style.scss';
import { isVideoType } from './utils';
import { clamp } from '../utils/math';
import Image from '../mobile/image';
import UnitControl from '../unit-control';
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
const MIN_POSITION_VALUE = 0;
const MAX_POSITION_VALUE = 100;
const FOCAL_POINT_UNITS = [{
  default: 50,
  label: '%',
  value: '%'
}];
function FocalPointPicker(props) {
  const {
    focalPoint,
    onChange,
    shouldEnableBottomSheetScroll,
    url
  } = props;
  const isVideo = isVideoType(url);
  const [containerSize, setContainerSize] = useState(null);
  const [sliderKey, setSliderKey] = useState(0);
  const [displayPlaceholder, setDisplayPlaceholder] = useState(true);
  const [videoNaturalSize, setVideoNaturalSize] = useState(null);
  const [tooltipVisible, setTooltipVisible] = useState(false);
  const locationPageOffsetX = useRef();
  const locationPageOffsetY = useRef();
  const videoRef = useRef(null);
  useEffect(() => {
    requestFocalPointPickerTooltipShown(tooltipShown => {
      if (!tooltipShown) {
        setTooltipVisible(true);
        setFocalPointPickerTooltipShown(true);
      }
    });
  }, []);

  // Animated coordinates for drag handle.
  const pan = useRef(new Animated.ValueXY()).current;

  /**
   * Set drag handle position anytime focal point coordinates change.
   * E.g. initial render, dragging range sliders.
   */
  useEffect(() => {
    if (containerSize) {
      pan.setValue({
        x: focalPoint.x * containerSize.width,
        y: focalPoint.y * containerSize.height
      });
    }
  }, [focalPoint, containerSize, pan]);

  // Pan responder to manage drag handle interactivity.
  const panResponder = useMemo(() => PanResponder.create({
    onStartShouldSetPanResponder: () => true,
    onStartShouldSetPanResponderCapture: () => true,
    onMoveShouldSetPanResponder: () => true,
    onMoveShouldSetPanResponderCapture: () => true,
    onPanResponderGrant: event => {
      shouldEnableBottomSheetScroll(false);
      const {
        locationX: x,
        locationY: y,
        pageX,
        pageY
      } = event.nativeEvent;
      locationPageOffsetX.current = pageX - x;
      locationPageOffsetY.current = pageY - y;
      pan.setValue({
        x,
        y
      }); // Set cursor to tap location.
      pan.extractOffset(); // Set offset to current value.
    },
    // Move cursor to match delta drag.
    onPanResponderMove: Animated.event([null, {
      dx: pan.x,
      dy: pan.y
    }], {
      useNativeDriver: false
    }),
    onPanResponderRelease: event => {
      shouldEnableBottomSheetScroll(true);
      pan.flattenOffset(); // Flatten offset into value.
      const {
        pageX,
        pageY
      } = event.nativeEvent;
      // Ideally, x and y below are merely locationX and locationY from the
      // nativeEvent. However, we are required to compute these relative
      // coordinates to workaround a bug affecting Android's PanResponder.
      // Specifically, dragging the handle outside the bounds of the image
      // results in inaccurate locationX and locationY coordinates to be
      // reported. https://github.com/facebook/react-native/issues/15290#issuecomment-435494944
      const x = pageX - locationPageOffsetX.current;
      const y = pageY - locationPageOffsetY.current;
      onChange({
        x: clamp(x / containerSize?.width, 0, 1).toFixed(2),
        y: clamp(y / containerSize?.height, 0, 1).toFixed(2)
      });
      // Slider (child of RangeCell) is uncontrolled, so we must increment a
      // key to re-mount and sync the pan gesture values to the sliders
      // https://github.com/callstack/react-native-slider/tree/v3.0.3#value
      setSliderKey(prevState => prevState + 1);
    }
  }), [containerSize, pan, onChange, shouldEnableBottomSheetScroll]);
  const mediaBackground = usePreferredColorSchemeStyle(styles.mediaBackground, styles.mediaBackgroundDark);
  const imagePreviewStyles = [displayPlaceholder && styles.mediaPlaceholder, styles.image];
  const videoPreviewStyles = [{
    aspectRatio: videoNaturalSize && videoNaturalSize.width / videoNaturalSize.height,
    // Hide Video component since it has black background while loading the source
    opacity: displayPlaceholder ? 0 : 1
  }, styles.video, displayPlaceholder && styles.mediaPlaceholder];
  const focalPointGroupStyles = [styles.focalPointGroup, {
    transform: [{
      translateX: pan.x.interpolate({
        inputRange: [0, containerSize?.width || 0],
        outputRange: [0, containerSize?.width || 0],
        extrapolate: 'clamp'
      })
    }, {
      translateY: pan.y.interpolate({
        inputRange: [0, containerSize?.height || 0],
        outputRange: [0, containerSize?.height || 0],
        extrapolate: 'clamp'
      })
    }]
  }];
  const FOCAL_POINT_SIZE = 50;
  const focalPointStyles = StyleSheet.flatten([styles.focalPoint, {
    height: FOCAL_POINT_SIZE,
    marginLeft: -(FOCAL_POINT_SIZE / 2),
    marginTop: -(FOCAL_POINT_SIZE / 2),
    width: FOCAL_POINT_SIZE
  }]);
  const onTooltipPress = () => setTooltipVisible(false);
  const onMediaLayout = event => {
    const {
      height,
      width
    } = event.nativeEvent.layout;
    if (width !== 0 && height !== 0 && (containerSize?.width !== width || containerSize?.height !== height)) {
      setContainerSize({
        width,
        height
      });
    }
  };
  const onImageDataLoad = () => setDisplayPlaceholder(false);
  const onVideoLoad = event => {
    const {
      height,
      width
    } = event.naturalSize;
    setVideoNaturalSize({
      height,
      width
    });
    setDisplayPlaceholder(false);
    // Avoid invisible, paused video on Android, presumably related to
    // https://github.com/react-native-video/react-native-video/issues/1979
    videoRef?.current.seek(0);
  };
  const onXCoordinateChange = x => onChange({
    x: (x / 100).toFixed(2)
  });
  const onYCoordinateChange = y => onChange({
    y: (y / 100).toFixed(2)
  });
  return /*#__PURE__*/_jsx(View, {
    style: styles.container,
    children: /*#__PURE__*/_jsxs(Tooltip, {
      onPress: onTooltipPress,
      visible: tooltipVisible,
      children: [/*#__PURE__*/_jsx(View, {
        style: [styles.media, mediaBackground],
        children: /*#__PURE__*/_jsxs(View, {
          ...panResponder.panHandlers,
          onLayout: onMediaLayout,
          style: styles.mediaContainer,
          children: [!isVideo && /*#__PURE__*/_jsx(Image, {
            editButton: false,
            highlightSelected: false,
            isSelected: !displayPlaceholder,
            height: "100%",
            url: url,
            style: imagePreviewStyles,
            onImageDataLoad: onImageDataLoad
          }), isVideo && /*#__PURE__*/_jsx(Video, {
            muted: true,
            paused: true,
            disableFocus: true,
            onLoad: onVideoLoad,
            ref: videoRef,
            resizeMode: "contain",
            source: {
              uri: url
            },
            style: videoPreviewStyles
          }), !displayPlaceholder && /*#__PURE__*/_jsxs(Animated.View, {
            pointerEvents: "none",
            style: focalPointGroupStyles,
            children: [/*#__PURE__*/_jsx(Tooltip.Label, {
              text: __('Drag to adjust focal point'),
              yOffset: -(FOCAL_POINT_SIZE / 2)
            }), /*#__PURE__*/_jsx(FocalPoint, {
              height: focalPointStyles.height,
              style: focalPointStyles,
              testID: "focal-point-picker-handle",
              width: focalPointStyles.width
            })]
          })]
        })
      }), /*#__PURE__*/_jsx(UnitControl, {
        label: __('X-Axis Position'),
        max: MAX_POSITION_VALUE,
        min: MIN_POSITION_VALUE,
        onChange: onXCoordinateChange,
        unit: "%",
        units: FOCAL_POINT_UNITS,
        value: Math.round(focalPoint.x * 100)
      }, `xAxis-${sliderKey}`), /*#__PURE__*/_jsx(UnitControl, {
        label: __('Y-Axis Position'),
        max: MAX_POSITION_VALUE,
        min: MIN_POSITION_VALUE,
        onChange: onYCoordinateChange,
        unit: "%",
        units: FOCAL_POINT_UNITS,
        value: Math.round(focalPoint.y * 100)
      }, `yAxis-${sliderKey}`)]
    })
  });
}
export default FocalPointPicker;
//# sourceMappingURL=index.native.js.map