import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2";
import { createVNode as _createVNode, Fragment as _Fragment } from "vue";
import _extends from "@babel/runtime/helpers/esm/extends";
import { computed, defineComponent, onMounted, onUnmounted, reactive, shallowRef, watch, cloneVNode, unref } from 'vue';
import classnames from '../../_util/classNames';
import Dialog from '../../vc-dialog';
import { dialogPropTypes } from '../../vc-dialog/IDialogPropTypes';
import addEventListener from '../../vc-util/Dom/addEventListener';
import KeyCode from '../../_util/KeyCode';
import { warning } from '../../vc-util/warning';
import useFrameSetState from './hooks/useFrameSetState';
import getFixScaleEleTransPosition from './getFixScaleEleTransPosition';
import { context } from './PreviewGroup';
const initialPosition = {
  x: 0,
  y: 0
};
export const previewProps = _extends(_extends({}, dialogPropTypes()), {
  src: String,
  alt: String,
  rootClassName: String,
  icons: {
    type: Object,
    default: () => ({})
  },
  minScale: Number,
  maxScale: Number,
  imageInfo: Object
});
const Preview = defineComponent({
  compatConfig: {
    MODE: 3
  },
  name: 'Preview',
  inheritAttrs: false,
  props: previewProps,
  emits: ['close', 'afterClose'],
  slots: Object,
  setup(props, _ref) {
    let {
      emit,
      attrs,
      slots
    } = _ref;
    const {
      rotateLeft,
      rotateRight,
      zoomIn,
      zoomOut,
      close,
      left,
      right,
      flipX,
      flipY
    } = reactive(props.icons);
    const {
      minScale = 1,
      maxScale = 50,
      imageInfo = {}
    } = reactive(props);
    const scale = shallowRef(1);
    const rotate = shallowRef(0);
    const flip = reactive({
      x: 1,
      y: 1
    });
    const [position, setPosition] = useFrameSetState(initialPosition);
    const onClose = () => emit('close');
    const imgRef = shallowRef();
    const originPositionRef = reactive({
      originX: 0,
      originY: 0,
      deltaX: 0,
      deltaY: 0
    });
    const isMoving = shallowRef(false);
    const groupContext = context.inject();
    const {
      previewUrls,
      current,
      isPreviewGroup,
      setCurrent
    } = groupContext;
    const previewGroupCount = computed(() => previewUrls.value.size);
    const previewUrlsKeys = computed(() => Array.from(previewUrls.value.keys()));
    const currentPreviewIndex = computed(() => previewUrlsKeys.value.indexOf(current.value));
    const combinationSrc = computed(() => {
      return isPreviewGroup.value ? previewUrls.value.get(current.value) : props.src;
    });
    const showLeftOrRightSwitches = computed(() => isPreviewGroup.value && previewGroupCount.value > 1);
    const showOperationsProgress = computed(() => isPreviewGroup.value && previewGroupCount.value >= 1);
    const lastWheelZoomDirection = shallowRef({
      wheelDirection: 0
    });
    const image = computed(() => _extends({
      url: combinationSrc.value,
      alt: props.alt
    }, imageInfo));
    const onAfterClose = () => {
      scale.value = 1;
      rotate.value = 0;
      flip.x = 1;
      flip.y = 1;
      setPosition(initialPosition);
      emit('afterClose');
    };
    const onZoomIn = isWheel => {
      if (!isWheel) {
        scale.value++;
      } else {
        scale.value += 0.5;
      }
      setPosition(initialPosition);
    };
    const onZoomOut = isWheel => {
      if (scale.value > 1) {
        if (!isWheel) {
          scale.value--;
        } else {
          scale.value -= 0.5;
        }
      }
      setPosition(initialPosition);
    };
    const onRotateRight = () => {
      rotate.value += 90;
    };
    const onRotateLeft = () => {
      rotate.value -= 90;
    };
    const onFlipX = () => {
      flip.x = -flip.x;
    };
    const onFlipY = () => {
      flip.y = -flip.y;
    };
    const onSwitchLeft = event => {
      event.preventDefault();
      // Without this mask close will abnormal
      event.stopPropagation();
      if (currentPreviewIndex.value > 0) {
        setCurrent(previewUrlsKeys.value[currentPreviewIndex.value - 1]);
      }
    };
    const onSwitchRight = event => {
      event.preventDefault();
      // Without this mask close will abnormal
      event.stopPropagation();
      if (currentPreviewIndex.value < previewGroupCount.value - 1) {
        setCurrent(previewUrlsKeys.value[currentPreviewIndex.value + 1]);
      }
    };
    const wrapClassName = classnames({
      [`${props.prefixCls}-moving`]: isMoving.value
    });
    const toolClassName = `${props.prefixCls}-operations-operation`;
    const iconClassName = `${props.prefixCls}-operations-icon`;
    const tools = [{
      icon: flipY,
      onClick: onFlipY,
      type: 'flipY'
    }, {
      icon: flipX,
      onClick: onFlipX,
      type: 'flipX'
    }, {
      icon: rotateLeft,
      onClick: onRotateLeft,
      type: 'rotateLeft'
    }, {
      icon: rotateRight,
      onClick: onRotateRight,
      type: 'rotateRight'
    }, {
      icon: zoomOut,
      onClick: onZoomOut,
      type: 'zoomOut',
      disabled: computed(() => scale.value === minScale)
    }, {
      icon: zoomIn,
      onClick: onZoomIn,
      type: 'zoomIn',
      disabled: computed(() => scale.value === maxScale)
    }];
    const onMouseUp = () => {
      if (props.visible && isMoving.value) {
        const width = imgRef.value.offsetWidth * scale.value;
        const height = imgRef.value.offsetHeight * scale.value;
        const {
          left,
          top
        } = imgRef.value.getBoundingClientRect();
        const isRotate = rotate.value % 180 !== 0;
        isMoving.value = false;
        const fixState = getFixScaleEleTransPosition(isRotate ? height : width, isRotate ? width : height, left, top);
        if (fixState) {
          setPosition(_extends({}, fixState));
        }
      }
    };
    const onMouseDown = event => {
      // Only allow main button
      if (event.button !== 0) return;
      event.preventDefault();
      // Without this mask close will abnormal
      event.stopPropagation();
      originPositionRef.deltaX = event.pageX - position.x;
      originPositionRef.deltaY = event.pageY - position.y;
      originPositionRef.originX = position.x;
      originPositionRef.originY = position.y;
      isMoving.value = true;
    };
    const onMouseMove = event => {
      if (props.visible && isMoving.value) {
        setPosition({
          x: event.pageX - originPositionRef.deltaX,
          y: event.pageY - originPositionRef.deltaY
        });
      }
    };
    const onWheelMove = event => {
      if (!props.visible) return;
      event.preventDefault();
      const wheelDirection = event.deltaY;
      lastWheelZoomDirection.value = {
        wheelDirection
      };
    };
    const onKeyDown = event => {
      if (!props.visible || !showLeftOrRightSwitches.value) return;
      event.preventDefault();
      if (event.keyCode === KeyCode.LEFT) {
        if (currentPreviewIndex.value > 0) {
          setCurrent(previewUrlsKeys.value[currentPreviewIndex.value - 1]);
        }
      } else if (event.keyCode === KeyCode.RIGHT) {
        if (currentPreviewIndex.value < previewGroupCount.value - 1) {
          setCurrent(previewUrlsKeys.value[currentPreviewIndex.value + 1]);
        }
      }
    };
    const onDoubleClick = () => {
      if (props.visible) {
        if (scale.value !== 1) {
          scale.value = 1;
        }
        if (position.x !== initialPosition.x || position.y !== initialPosition.y) {
          setPosition(initialPosition);
        }
      }
    };
    let removeListeners = () => {};
    onMounted(() => {
      watch([() => props.visible, isMoving, imgRef], () => {
        removeListeners();
        let onTopMouseUpListener;
        let onTopMouseMoveListener;
        const onMouseUpListener = addEventListener(imgRef.value, 'mouseup', onMouseUp, false);
        const onMouseMoveListener = addEventListener(imgRef.value, 'mousemove', onMouseMove, false);
        const onScrollWheelListener = addEventListener(imgRef.value, 'wheel', onWheelMove, {
          passive: false
        });
        const onKeyDownListener = addEventListener(window, 'keydown', onKeyDown, false);
        try {
          // Resolve if in iframe lost event
          /* istanbul ignore next */
          if (window.top !== window.self) {
            onTopMouseUpListener = addEventListener(window.top, 'mouseup', onMouseUp, false);
            onTopMouseMoveListener = addEventListener(window.top, 'mousemove', onMouseMove, false);
          }
        } catch (error) {
          /* istanbul ignore next */
          warning(false, `[vc-image] ${error}`);
        }
        removeListeners = () => {
          onMouseUpListener.remove();
          onMouseMoveListener.remove();
          onScrollWheelListener.remove();
          onKeyDownListener.remove();
          /* istanbul ignore next */
          if (onTopMouseUpListener) onTopMouseUpListener.remove();
          /* istanbul ignore next */
          if (onTopMouseMoveListener) onTopMouseMoveListener.remove();
        };
      }, {
        flush: 'post',
        immediate: true
      });
      watch([lastWheelZoomDirection], () => {
        const {
          wheelDirection
        } = lastWheelZoomDirection.value;
        if (wheelDirection > 0) {
          onZoomOut(true);
        } else if (wheelDirection < 0) {
          onZoomIn(true);
        }
      });
    });
    onUnmounted(() => {
      removeListeners();
    });
    return () => {
      var _a, _b;
      const {
        visible,
        prefixCls,
        rootClassName
      } = props;
      const toolsNode = tools.map(_ref2 => {
        let {
          icon: IconType,
          onClick,
          type,
          disabled
        } = _ref2;
        return _createVNode("div", {
          "class": classnames(toolClassName, {
            [`${props.prefixCls}-operations-operation-${type}`]: true,
            [`${props.prefixCls}-operations-operation-disabled`]: disabled && (disabled === null || disabled === void 0 ? void 0 : disabled.value)
          }),
          "onClick": onClick,
          "key": type
        }, [cloneVNode(IconType, {
          class: iconClassName
        })]);
      });
      const toolbarNode = _createVNode("div", {
        "class": `${props.prefixCls}-operations`
      }, [toolsNode]);
      return _createVNode(_Fragment, null, [_createVNode(Dialog, _objectSpread(_objectSpread({}, attrs), {}, {
        "transitionName": props.transitionName,
        "maskTransitionName": props.maskTransitionName,
        "closable": false,
        "keyboard": true,
        "prefixCls": prefixCls,
        "onClose": onClose,
        "afterClose": onAfterClose,
        "visible": visible,
        "wrapClassName": wrapClassName,
        "rootClassName": rootClassName,
        "getContainer": props.getContainer
      }), {
        default: () => [_createVNode("div", {
          "class": `${props.prefixCls}-img-wrapper`,
          "style": {
            transform: `translate3d(${position.x}px, ${position.y}px, 0)`
          }
        }, [_createVNode("img", {
          "onMousedown": onMouseDown,
          "onDblclick": onDoubleClick,
          "ref": imgRef,
          "class": `${props.prefixCls}-img`,
          "src": combinationSrc.value,
          "alt": props.alt,
          "style": {
            transform: `scale3d(${flip.x * scale.value}, ${flip.y * scale.value}, 1) rotate(${rotate.value}deg)`
          }
        }, null)])]
      }), visible && _createVNode("div", {
        "class": classnames(`${props.prefixCls}-operations-wrapper`, rootClassName)
      }, [_createVNode("button", {
        "class": `${props.prefixCls}-close`,
        "onClick": onClose
      }, [((_a = slots.closeIcon) === null || _a === void 0 ? void 0 : _a.call(slots, {
        onClose
      })) || close]), showLeftOrRightSwitches.value && _createVNode(_Fragment, null, [_createVNode("div", {
        "class": classnames(`${prefixCls}-switch-left`, {
          [`${props.prefixCls}-switch-left-disabled`]: currentPreviewIndex.value === 0
        }),
        "onClick": onSwitchLeft
      }, [left]), _createVNode("div", {
        "class": classnames(`${prefixCls}-switch-right`, {
          [`${props.prefixCls}-switch-right-disabled`]: currentPreviewIndex.value === previewGroupCount.value - 1
        }),
        "onClick": onSwitchRight
      }, [right])]), _createVNode("div", {
        "class": [`${props.prefixCls}-footer`]
      }, [showOperationsProgress.value && _createVNode("div", {
        "class": `${props.prefixCls}-progress`
      }, [`${currentPreviewIndex.value + 1} / ${previewGroupCount.value}`]), slots.toolbarRender ? (_b = slots.toolbarRender) === null || _b === void 0 ? void 0 : _b.call(slots, _extends({
        originalNodes: toolsNode,
        actions: {
          onFlipY,
          onFlipX,
          onRotateLeft,
          onRotateRight,
          onZoomOut,
          onZoomIn
        },
        transform: {
          x: position.x,
          y: position.y,
          scale: scale.value,
          rotate,
          flip
        },
        image: unref(image)
      }, groupContext ? {
        current: currentPreviewIndex.value,
        total: previewGroupCount.value
      } : {})) : toolbarNode])])]);
    };
  }
});
export default Preview;