"use strict";

var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.default = void 0;
var _reactNative = require("react-native");
var _reactNativeVideo = _interopRequireDefault(require("react-native-video"));
var _reactNativeBridge = require("@wordpress/react-native-bridge");
var _i18n = require("@wordpress/i18n");
var _element = require("@wordpress/element");
var _compose = require("@wordpress/compose");
var _focalPoint = _interopRequireDefault(require("./focal-point"));
var _tooltip = _interopRequireDefault(require("./tooltip"));
var _style = _interopRequireDefault(require("./style.scss"));
var _utils = require("./utils");
var _math = require("../utils/math");
var _image = _interopRequireDefault(require("../mobile/image"));
var _unitControl = _interopRequireDefault(require("../unit-control"));
var _jsxRuntime = require("react/jsx-runtime");
/**
 * External dependencies
 */

/**
 * WordPress dependencies
 */

/**
 * Internal dependencies
 */

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 = (0, _utils.isVideoType)(url);
  const [containerSize, setContainerSize] = (0, _element.useState)(null);
  const [sliderKey, setSliderKey] = (0, _element.useState)(0);
  const [displayPlaceholder, setDisplayPlaceholder] = (0, _element.useState)(true);
  const [videoNaturalSize, setVideoNaturalSize] = (0, _element.useState)(null);
  const [tooltipVisible, setTooltipVisible] = (0, _element.useState)(false);
  const locationPageOffsetX = (0, _element.useRef)();
  const locationPageOffsetY = (0, _element.useRef)();
  const videoRef = (0, _element.useRef)(null);
  (0, _element.useEffect)(() => {
    (0, _reactNativeBridge.requestFocalPointPickerTooltipShown)(tooltipShown => {
      if (!tooltipShown) {
        setTooltipVisible(true);
        (0, _reactNativeBridge.setFocalPointPickerTooltipShown)(true);
      }
    });
  }, []);

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

  /**
   * Set drag handle position anytime focal point coordinates change.
   * E.g. initial render, dragging range sliders.
   */
  (0, _element.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 = (0, _element.useMemo)(() => _reactNative.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: _reactNative.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: (0, _math.clamp)(x / containerSize?.width, 0, 1).toFixed(2),
        y: (0, _math.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 = (0, _compose.usePreferredColorSchemeStyle)(_style.default.mediaBackground, _style.default.mediaBackgroundDark);
  const imagePreviewStyles = [displayPlaceholder && _style.default.mediaPlaceholder, _style.default.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
  }, _style.default.video, displayPlaceholder && _style.default.mediaPlaceholder];
  const focalPointGroupStyles = [_style.default.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 = _reactNative.StyleSheet.flatten([_style.default.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__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
    style: _style.default.container,
    children: /*#__PURE__*/(0, _jsxRuntime.jsxs)(_tooltip.default, {
      onPress: onTooltipPress,
      visible: tooltipVisible,
      children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
        style: [_style.default.media, mediaBackground],
        children: /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
          ...panResponder.panHandlers,
          onLayout: onMediaLayout,
          style: _style.default.mediaContainer,
          children: [!isVideo && /*#__PURE__*/(0, _jsxRuntime.jsx)(_image.default, {
            editButton: false,
            highlightSelected: false,
            isSelected: !displayPlaceholder,
            height: "100%",
            url: url,
            style: imagePreviewStyles,
            onImageDataLoad: onImageDataLoad
          }), isVideo && /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNativeVideo.default, {
            muted: true,
            paused: true,
            disableFocus: true,
            onLoad: onVideoLoad,
            ref: videoRef,
            resizeMode: "contain",
            source: {
              uri: url
            },
            style: videoPreviewStyles
          }), !displayPlaceholder && /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.Animated.View, {
            pointerEvents: "none",
            style: focalPointGroupStyles,
            children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_tooltip.default.Label, {
              text: (0, _i18n.__)('Drag to adjust focal point'),
              yOffset: -(FOCAL_POINT_SIZE / 2)
            }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_focalPoint.default, {
              height: focalPointStyles.height,
              style: focalPointStyles,
              testID: "focal-point-picker-handle",
              width: focalPointStyles.width
            })]
          })]
        })
      }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_unitControl.default, {
        label: (0, _i18n.__)('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__*/(0, _jsxRuntime.jsx)(_unitControl.default, {
        label: (0, _i18n.__)('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}`)]
    })
  });
}
var _default = exports.default = FocalPointPicker;
//# sourceMappingURL=index.native.js.map