import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { Modal } from 'antd';
import "./dragDialog.scss";
import { domUtils, getLagerThanMaxZindex, isMobile } from '../../utils/helper';
import { Icon } from '../icons';
import { inject, observer } from 'mobx-react';
import { MinusOutlined, PushpinFilled, PushpinOutlined, VerticalLeftOutlined, VerticalRightOutlined } from '@ant-design/icons';
import { Rnd } from 'react-rnd';
import { ResizeEvent } from '../../types';
import { throttle } from 'lodash';
export interface IDialogProps {
  /** 自定义类名 */
  className: string;
  /** 确定文字 */
  okText: string;
  /** 取消文字 */
  cancelText: string;
  /** 标题 */
  title: string | React.ReactNode;
  /** 宽度 */
  width: string | number;
  /** 高度 */
  height: string | number;
  style?: keyof JSX.IntrinsicElements['div']['style'];
  /** 居中显示 */
  centered: boolean;
  /** 是否显示 */
  dialogVisible: boolean;
  /** 是否可以调整大小 */
  resizeable: boolean;//
  getContainer: () => HTMLElement | HTMLElement;
  /** 取消 */
  onCancel: (e: React.MouseEvent) => void;
  /** 确认 */
  onOk: (e: React.MouseEvent) => void;
  /** 底部按钮 */
  footer?: React.ReactNode;
  /** 是否可拖拽 */
  drag: boolean;
  wrapClassName: string;
  maskClosable: boolean;
  /** 是否可以点击下层元素 */
  canClickBelowDom?: boolean;
  /** 是否可以调整为固定到右侧 */
  setFixRight?: boolean;
  /** 是否可以最大化 */
  setMaxSize?: boolean;
  /** 是否默认最大化 */
  defaultMaxSize?: boolean;
  /** 是否最小化 true为是 false为否 */
  hide?: boolean;
  /** 隐藏弹窗 */
  onHide?: (e: React.MouseEvent) => void;
  /** 展示弹窗 */
  onShow?: (e: React.MouseEvent) => void;
  /** 最小化的情况下是否展示最小化标题 配置最小化才生效 */
  showMinTitle?: boolean;
  /** 是否隐藏头部 */
  hideTitle?: boolean;
  /** 是否可关闭右下角的浮窗 */
  closable?: boolean;
  /** 阻止enter快捷键 如果为true，阻止当前快捷键enter */
  preventEnter?: boolean;
  /** 是否移动端 */
  mode: 'mobile' | 'pc';
  /** 是否显示遮罩层 */
  mask: boolean;
  /** 此Dialog是查询器时,查询器此时是否打开 */
  queryShow?: boolean;
  /** 最小高度 */
  minHeight?: number;
  /** 最小宽度 */
  minWidth?: number;
  /** 最大宽度 */
  maxWidth?: number | string;
  /** 最大高度 */
  maxHeight?: number | string;
  /** 进入弹窗的上一个获取焦点的dom */
  entryDom?: HTMLDivElement;
  keyHandle?: (e: React.KeyboardEvent) => void;
  /** 点击关闭是否需要二次确认 */
  popConfirm?: React.ReactNode;
  /** 是否启用键盘事件 */
  keyboard?: boolean;
  /** 存储弹窗最终配置的key值，配置后用这个key进行存取值 */
  cacheConfigKey?: string;
  /** 最小化的容器的className */
  miniTitleWrapperClassName?: string;
  /** 最小化容器存储最终配置的key，有key就支持存储到本地，下次点开的时候，可以恢复配置 */
  miniTitleConfigKey?: string;
  /** 是否将固定在右侧的弹窗显示,仅在弹窗固定右侧后，再次触发用 */
  forceShowFixModal?: boolean;
  /** 隐藏图标的dom */
  hiddenBtn?: React.ReactNode;
  /** Resize的时候触发重新赋值ModalBody的height, 开启后会在resizing的期间频繁触发 */
  forceCalcOnResize?: boolean;
  /** 是否要pin到页面右侧 */
  pinRight?: boolean;
  /** 是否初始化的时候占满高度 */
  fullHeightOnInit?: boolean;
  /** 设置弹窗边界 默认: window */
  bounds?: string | boolean;
  /** 其余属性 */
  [key: string]: any;
}
/** 缓存模态框配置 */
interface ICacheDialog {
  x: number;
  y: number;
  width: number;
  height: number;
  transform?: string;
}

// const FLModal: React.FC<IDialogProps> = (props) => {
const FLModal: React.FC<IDialogProps> = inject('modalStore')(observer(({ modalStore, ...props }) => {
  // 默认属性
  const defaultProps: Partial<IDialogProps> = {
    okText: '确定',
    cancelText: '取消',
    title: '弹窗',
    centered: true,
    resizeable: false,
    drag: true,
    maskClosable: false,
    mode: 'pc',
    closable: true,
    mask: true,
    keyboard: true,
    minWidth: 400,
    bounds: 'window'
  };
  const { drag, title, className, mode, closable, hideTitle, canClickBelowDom, dialogVisible, keyHandle, popConfirm, children, minHeight = 300, minWidth, resizeable, keyboard, cacheConfigKey = '', miniTitleWrapperClassName = '', forceShowFixModal, hiddenBtn, fullHeightOnInit, forceCalcOnResize, pinRight, bounds = 'window', defaultMaxSize = false} = { ...defaultProps, ...props };
  const [maxSize, setMaxSize] = useState(false);
  const [resizableWidth, setResizableWidth] = useState(props.width);
  const [resizableHeight, _setResizableHeight] = useState(props.height);
  const [position, setPosition] = useState({ x: 0, y: 0 });
  const [modalId] = useState(`${Date.now()}`);
  const [fixRight, setFixRight] = useState(false);
  const [pinToRight, setPinToRight] = useState(false);
  const [stickyRight, setStickyRight] = useState(false);
  // const [modalZIndex, setModalZIndex] = useState(getLagerThanMaxZindex());
  const [modalZIndex, setModalZIndex] = useState(999);
  const [pageContentId, setPageContentId] = useState('');
  const isFixRight = useRef(false);
  const domRef = useRef<HTMLElement | undefined | null>(undefined);
  const minTitleDomRef = useRef(null);
  const titleDomHigh = useRef(0);
  const titleDom = useRef<HTMLDivElement>(null);
  const dragModalRef = useRef<HTMLElement>(null);
  const dragTimer = useRef();
  /** 拖拽容器主体ref */
  const rndMainRef = useRef();
  const fixRightStyleRef: any = useRef({
    position: 'fixed',
    top: '0',
    // height: '100vh',
    right: '0',
  })
  const maxSizeStyleRef: any = useRef({
    position: 'fixed',
    top: '0',
    // height: '100vh',
    right: '0',
  })
  const titleMinDom = useRef<HTMLDivElement>(null);
  const setResizableHeight = (high: number) => {
    _setResizableHeight(props.footer ? (high - 53) : high)

  }
  // const moving = useRef(false);
  const lastX = useRef<number | undefined | null>(0);
  const lastY = useRef<number | undefined | null>(0);
  /** 最后模态框的定位 */
  const lastPosition = useRef<{ x: number; y: number }>({ x: 0, y: 0 });

  const originModalStyleRef = useRef<any>({});
  const manualFix = useRef(false);
  let isMiniTitleDragging = false;
  // 获取dom实例
  const contentRef = useCallback((ref) => {

    // 重置一下偏移位置
    setPosition({ x: 0, y: 0 });
    // 重置实例的时候 （重置/初始化）titleDom实例高度
    if (!titleDomHigh.current && titleDom.current) {
      titleDomHigh.current = titleDom.current?.getBoundingClientRect().height;
    }
    if (ref) {
      // 如果配置默认全屏，则切换全屏
      if (defaultMaxSize) {
        toggleMaxSize();
      }
      const pageContentDom = domUtils.closest(ref as HTMLElement, '.main-page-content');
      const pageContentIdMatch = pageContentDom?.className.split(' ').find((item) => item.includes('page-content-id_')) ?? '';
      setPageContentId(pageContentIdMatch);
      domRef.current = domUtils.closest(ref as HTMLElement, '.ant-modal-content')?.parentElement;
      // 如果允许点击下层按钮 把root的事件置为none
      if (canClickBelowDom) {
        const rootDom = domUtils.closest(ref as HTMLElement, '.ant-modal-wrap.drag-dialog')
        if (rootDom) {
          rootDom.style.pointerEvents = 'none'
          // rootDom.style.zIndex = modalZIndex
        }
      }
      const cachedConfig = localStorage.getItem(cacheConfigKey);

      // 没有缓存的配置的话，则走初始化配置
      cacheConfigKey ? generateCachedModalPosition(cachedConfig as string) : generateModalPosition();
      /** 初始化mini-title操作框的位置 */
      if (props.showMinTitle) {
        const x = getClientWidth() - 100;
        const y = 100;
        minTitleDomRef.current!.updatePosition({ x, y });
      }
      // 广播一下变化事件
      disPatchResize()
    }
  }, []);
  // enter 键盘事件监听 弹窗内置快捷键
  const onKeyDown = useCallback((e: any) => {
    e.stopPropagation();
    if (e.key == 'Escape') {
      btnCancel(e);
    }
    if (e.key === 'Enter' && props.preventEnter) {
      btnOk(e);
    }
  }, []);

  const btnOk = useCallback((e: React.MouseEvent) => {
    let { onOk } = props;
    onOk && onOk(e);
  }, []);

  const footDom = useCallback(() => {
    let { okText, cancelText, onCancel, onOk } = props;
    return (
      <div className="foot-mb">
        <div onClick={(e: React.MouseEvent) => onCancel && onCancel(e)}>{cancelText}</div>
        <div onClick={(e: React.MouseEvent) => onOk && onOk(e)}>{okText}</div>
      </div>
    );
  }, []);
  // 记录原来窗体信息
  const recordOriginSize = (Modalbody: HTMLElement) => {
    // 记录原来的偏移量
    originModalStyleRef.current.transform = domRef?.current?.style.transform
    // 记录原来的宽度
    originModalStyleRef.current.width = domRef?.current?.style.width
    originModalStyleRef.current.clientWidth = domRef?.current?.clientWidth
    // 记录原来的弹窗高度
    originModalStyleRef.current.height = Modalbody.getBoundingClientRect().height

    originModalStyleRef.current.maxHeight = Modalbody.style.maxHeight
    originModalStyleRef.current.maxWidth = Modalbody.style.maxWidth
    originModalStyleRef.current.offsetLeft = Modalbody.getBoundingClientRect().left;
  }
  const toggleMaxSize = () => {
    // 全屏的时候需要将原先固定至右侧的占用给去除
    if (pinRight && (pinToRight || isFixRight.current)) {
      handlePinRightSize(true);
      setPinToRight(false);
      toggleDialogFixRight();
    }
    setMaxSize(isMaxSize => {
      const Modalbody = domRef.current?.querySelector('.ant-modal-body') as HTMLElement
      if (Modalbody?.style) {
        // 变为原有大小的时候
        if (isMaxSize) {
          if (defaultMaxSize) {
            generateModalPosition();
          } else {
            if (domRef?.current?.style) {
              setPosition(lastPosition.current);
              setResizableWidth(originModalStyleRef.current.width);
              setResizableHeight(originModalStyleRef.current.height + titleDomHigh.current);
              domRef.current.style.transform = originModalStyleRef.current.transform
              domRef.current.style.width = originModalStyleRef.current.width
            }
            Modalbody.style.height = `${originModalStyleRef.current.height}px`;
            Modalbody.style.maxHeight = originModalStyleRef.current.maxHeight
            Modalbody.style.maxWidth = originModalStyleRef.current.maxWidth
          }
        } else {
          // 设置全屏, 需要减去导航栏高度
          const tabsContentHeight = domUtils.closest(domRef.current as HTMLElement, '.tabs-content')?.clientHeight ?? 45;

          const domHeight = getClientHeight() - tabsContentHeight;
          const { left } = domRef.current?.getBoundingClientRect();
          lastPosition.current = { x: left, y: tabsContentHeight }
          // Modalbody.style.width = `${domRef.current?.clientWidth}px`;
          Modalbody.style.height = `${domHeight - titleDomHigh.current}px`;
          Modalbody.style.maxHeight = 'unset'
          Modalbody.style.maxWidth = 'unset'
          recordOriginSize(Modalbody);
          // 如果有resize 把body也resize了
          if (domRef?.current?.style) {
            domRef.current.style.transform = ''
            domRef.current.style.width = '100vw'
          }
          setPosition({ x: 0, y: tabsContentHeight });
          setResizableWidth('100vw');
          setResizableHeight(domHeight);
        }
      }

      return !isMaxSize
    })
  };
  /** 切换是否固定到右侧 */
  const toggleDialogFixRight = (e?: any) => {
    setFixRight(e => {
      const Modalbody = domRef.current?.querySelector('.ant-modal-body') as HTMLElement
      if (Modalbody?.style) {
        // 变为不固定的时候
        if (e) {
          isFixRight.current = false;
          if (domRef?.current?.style) {
            // 非点击按钮触发解除固定 ，如果是手动拖拽触发，则强制从最右侧开始
            if (!manualFix.current) {
              setPosition({
                x: lastPosition.current.x,
                y: 0
              });

              setResizableHeight(originModalStyleRef.current.height);
              // domRef.current.style.transform = originModalStyleRef.current.transform;
              Modalbody.style.height = `${originModalStyleRef.current.height - titleDomHigh.current}px`;
            } else {
              if (!pinRight) {
                const { y } = lastPosition.current;
                const originHeight = originModalStyleRef.current.height + titleDomHigh.current;
                const diffHeight = getClientHeight() - originHeight;
                if (y > diffHeight) {
                  lastPosition.current = { ...lastPosition.current, y: diffHeight };
                }
                setPosition(lastPosition.current);
                setResizableHeight(originHeight);
                Modalbody.style.height = `${originModalStyleRef.current.height}px`;
              }
              // domRef.current.style.transform = originModalStyleRef.current.transform
            }
          }
          Modalbody.style.maxHeight = originModalStyleRef.current.maxHeight
          Modalbody.style.maxWidth = originModalStyleRef.current.maxWidth
        } else {
          // 调整为固定到右侧
          const offsetX = getClientWidth() - 450;
          const { left, top } = domRef.current?.getBoundingClientRect();
          const tabsContentHeight = domUtils.closest(domRef.current as HTMLElement, '.tabs-content')?.clientHeight ?? 45;

          // const resizeDom = mainPage?.querySelector('.resize-container') as HTMLElement;
          const realHeight = getClientHeight() - tabsContentHeight;

          lastPosition.current = { x: left, y: top }
          // if (pinRight) {
          setPosition({
            x: offsetX,
            y: tabsContentHeight
          });
          setResizableWidth(450);
          setResizableHeight(realHeight);

          // 将modalBody样式重置
          if (domRef.current?.style) {
            domRef.current.style.width = '450px';
          }
          Modalbody.style.height = `${realHeight - titleDomHigh.current}px`;
          Modalbody.classList.remove('isMinWidth');
          // }
          //  else {
          //   setPosition({
          //     x: offsetX,
          //     y: 0
          //   });
          //   // 将modalBody样式重置
          //   Modalbody.style.height = `calc(100vh - ${titleDomHigh.current}px)`;
          //   setResizableHeight('100vh');
          // }
          recordOriginSize(Modalbody)
          isFixRight.current = true;

          // onTitleMouseEnter()
        }
      }
      return !e
    })
    setStickyRight(false);
  };
  const dispatchTimer = useRef();
  const disPatchResize = () => {
    clearTimeout(dispatchTimer.current);
    // 动画帧的变化会造成高度计算不对 变化时间是.3s 故按照3s计算
    dispatchTimer.current = setTimeout(() => {
      document.body.dispatchEvent(
        new Event(ResizeEvent.DIALOGRESIZEENDEVENT)
      );
    }, 250)
  }
  // 固定解除 最大最小调整 的时候触发重绘
  useEffect(() => {
    disPatchResize()
  }, [fixRight, maxSize])
  // 销毁定时器等
  useEffect(() => {
    window.addEventListener('resize', handleWindowResize);
    return () => {
      clearTimeout(dragTimer.current);
      clearTimeout(dispatchTimer.current);
      dragTimer.current = null;
      dispatchTimer.current = null;
      window.removeEventListener('resize', handleWindowResize);
    }
  }, []);
  useEffect(() => {
    if (dialogVisible && !props.hide) {
      disPatchResize();
    }
  }, [props.hide, dialogVisible]);
  useEffect(() => {
    /** 仅在固定在右侧的时候，手动触发显示 */
    if (forceShowFixModal && dialogVisible && (!pinRight && (fixRight || isFixRight.current))) {
      onTitleMouseEnter()
    }
  }, [forceShowFixModal]);

  /** 监听浏览器窗口大小改变 */
  const handleWindowResize = throttle(() => {
    const Modalbody = domRef.current?.querySelector('.ant-modal-body') as HTMLElement
    if (pinRight) {
      // 如果已经固定到右侧，则将始终保持贴在容器中
      if (pinToRight || isFixRight.current) {
        // 调整为固定到右侧
        const offsetX = getClientWidth() - (domRef.current?.clientWidth ?? 0);
        const { left, top } = domRef.current?.getBoundingClientRect();
        const tabsContentHeight = domUtils.closest(domRef.current as HTMLElement, '.tabs-content')?.clientHeight ?? 45;
        // const resizeDom = mainPage?.querySelector('.resize-container') as HTMLElement;
        const realHeight = getClientHeight() - tabsContentHeight;

        lastPosition.current = { x: left, y: top }
        setPosition({
          x: offsetX,
          // y: getClientHeight() - realHeight
          y: tabsContentHeight
        });
        setResizableHeight(realHeight);
        // resizeDom!.style!.height = `${realHeight}px`;
        // 将modalBody样式重置
        Modalbody.style.height = `${realHeight - titleDomHigh.current}px`;
      }
    }

  }, 300);
  /** 隐藏模态框 */
  const hideDialog = (e: any) => {
    // 最小化以后重置这些状态
    setFixRight(false);
    isFixRight.current = false;
    // 全屏状态下，触发隐藏模态框不清空状态
    // setMaxSize(false);
    if (!maxSize || fixRight) {
      originModalStyleRef.current = {}
    }
    const { onHide } = props;

    setPinToRight(false);
    handlePinRightSize(true);
    onHide && onHide(e);
  };
  /** 显示模态框 */
  const showDialog = useCallback((e: any) => {
    const { onShow } = props;
    onShow && onShow(e);
  }, []);
  /** 关闭模态框 */
  const btnCancel = (e: React.MouseEvent) => {
    setFixRight(false);
    setMaxSize(false);
    isFixRight.current = false;
    originModalStyleRef.current = {};
    setPinToRight(false);
    handlePinRightSize(true);
    const { onCancel } = props;
    onCancel && onCancel(e);
  };
  // 获取偏移量
  const getMoveDistance = useCallback((e: any) => {
    let body: HTMLElement = document.body;
    let pos = domRef.current?.getBoundingClientRect();
    if (!pos) return { moveX: 0, moveY: 0 };
    let maxWidth = body.clientWidth
    let maxHeight = body.clientHeight + 0.75 * pos.height;
    const minWidth = -0.75 * pos.width;
    const minHeight = 0; // 顶部不能超过
    if (lastX.current !== null && lastY.current !== null) {
      const dx = e.clientX - lastX.current;
      const dy = e.clientY - lastY.current;

      let newDX = dx;
      let newDY = dy;


      if (pos.left + pos.width >= maxWidth && dx > 0) {
        newDX = 0;
      } else if (pos.left + pos.width + dx >= maxWidth) {
        newDX = maxWidth - pos.left - pos.width;
      } else if ((pos.left < minWidth && dx < 0) || pos.left + dx < minWidth) {
        newDX = 0;
      }

      if (pos.top + pos.height >= maxHeight && dy > 0) {
        newDY = 0;
      } else if (pos.top + pos.height + dy >= maxHeight) {
        newDY = maxHeight - pos.top - pos.height;
      } else if ((pos.top < minHeight && dy < 0) || pos.top + dy < minHeight) {
        newDY = 0;
      }
      return { moveX: newDX, moveY: newDY };
    } else {
      return { moveX: 0, moveY: 0 };
    }
  }, []);

  /** 当模态框持续拖拽时触发 */
  const onDrag = useCallback((e, d) => {
    if (props.setFixRight) {
      const { node } = d;
      const { right: offsetRight } = node.getBoundingClientRect();
      const documentClientWidth = getClientWidth();
      const isStickyRight = documentClientWidth - offsetRight < 10;
      setStickyRight(isStickyRight);
      if (isFixRight.current) {
        toggleDialogFixRight();
      }
    }
  }, []);
  const toggleDialogPointEvent = useCallback((event: string = 'none') => {
    if (canClickBelowDom) {
      const rootDom = document.documentElement.querySelector('.ant-modal-wrap.drag-dialog') as HTMLElement;
      if (rootDom) rootDom.style.pointerEvents = event
    }
  }, []);
  /** 当开始拖拽的时候，给模态框添加dragging样式 */
  const onTitleDragStart = () => {
    isMiniTitleDragging = true;
    dragModalRef.current?.classList?.add('isDragging')
  };
  /** 当结束拖拽的时候，给模态框去除dragging样式 */
  const onTitleDragStop = () => {
    clearTimeout(dragTimer.current);
    dragTimer.current = setTimeout(() => {
      isMiniTitleDragging = false;
    }, 250);
    dragModalRef.current?.classList?.remove('isDragging')
  };
  /** 当模态框开始拖拽时 - 暂停覆盖zIndex */
  const onDragStart = (e, d) => {
    /** 将当前选中的模态框赋予最高zIndex */
    const { node } = d;
    const newIndex = getLagerThanMaxZindex();
    const finalIndex = newIndex - 1 <= modalZIndex ? modalZIndex : newIndex;
    const rootDom = domUtils.closest(node as HTMLDivElement, '.ant-modal-wrap.drag-dialog');
    if (rootDom) {
      rootDom.style.zIndex = finalIndex
      setModalZIndex(finalIndex);
    }
  }
  /** 当模态框停止拖拽时触发 */
  const onDragStop = useCallback((e, d) => {
    toggleDialogPointEvent();
    const { node, x, y } = d;

    // 缓存最后的位置
    lastPosition.current = { x, y };
    // 配置坐标
    setPosition({ x, y });

    const documentClientWidth = getClientWidth();
    const { right: offsetRight, left: offsetLeft } = node.getBoundingClientRect();
    const isStickyRight = props.setFixRight ? documentClientWidth - offsetRight < 10 : 0;
    if (props.setFixRight) {
      if (isStickyRight) {
        const height = getClientHeight();
        setPosition({ x: offsetLeft, y: 0 });

        // 将modalBody样式重置
        const modalBody = node.querySelector('.ant-modal-body');
        recordOriginSize(modalBody)
        modalBody.style.height = `calc(100vh - ${titleDomHigh.current}px)`;
        setResizableHeight(height);
      }
      setFixRight(isStickyRight);
      // 用useState获取到的值都是false，先用ref的值一起判断
      isFixRight.current = isStickyRight;
    }
    const configs: ICacheDialog = {
      x,
      y,
      width: node.clientWidth,
      height: node.clientHeight
    }
    requestAnimationFrame(() => {
      if (props.setFixRight) {
        setStickyRight(false);
      }
      if (!isStickyRight) {
        configs['transform'] = domRef.current?.style.transform ?? '';
      }
      cacheModalConfig(configs);
    });
  }, []);
  const onResize = throttle((e, direction, refEl, d, position) => {
    const { clientWidth, clientHeight } = refEl;
    setResizableWidth(clientWidth);
    setResizableHeight(clientHeight);

    if (forceCalcOnResize) {
      const modalBody = refEl.querySelector('.ant-modal-body');
      // const isMinWidth = clientWidth === minWidth;
      if (modalBody.style) {
        modalBody.style.height = (clientHeight - titleDomHigh.current) + 'px';
        // modalBody.classList[isMinWidth ? 'add' : 'remove']?.('isMinWidth');
      }
    }
  }, 300);
  const onResizeStop = (e, direction, refEl, d, position) => {
    const { offsetWidth, offsetHeight, clientWidth, clientHeight, style } = refEl;
    setPosition(position);
    if ((fixRight || isFixRight.current) && (!pinToRight || !pinRight)) {
      onTitleMouseEnter()

    } else if (pinRight && (pinToRight || isFixRight.current) || !fixRight && !isFixRight.current) {
      // lastPosition.current = position;

      const cacheConfigs = {
        ...position,
        width: clientWidth,
        height: clientHeight,
        transform: style.transform
      };
      cacheModalConfig(cacheConfigs);
    }
    // rndMainRef.current!.updatePosition(position);

    const isMinWidth = clientWidth === minWidth;
    const modalBody = refEl.querySelector('.ant-modal-body');
    if (modalBody.style) {
      modalBody.style.height = (clientHeight - titleDomHigh.current) + 'px';
      modalBody.classList[isMinWidth ? 'add' : 'remove']?.('isMinWidth');
    }
    disPatchResize();

    pinRight && pinToRight && handlePinRightSize(false);
  };
  const getFixedHoverTitle = useCallback(() => {
    return titleDom.current?.querySelector('.fixed-hover-title');
  }, []);
  /** 当鼠标离开Modal本体，将自身隐藏 - 暂时不引用 */
  const onMouseLeave = useCallback((e) => {
    if (isFixRight.current) {
      getFixedHoverTitle()?.classList.add('show');
      domRef.current.style.transform = `translate(${getClientWidth()}px, 0)`
    }
    modalStore?.defineModalId?.('');
  }, []);

  // 鼠标从固定在右侧的标题进入时，将显示整个Modal，并将自身隐藏
  const onTitleMouseEnter = useCallback(() => {
    requestAnimationFrame(() => {
      const offsetL = getClientWidth() - (domRef.current?.clientWidth ?? 0);
      domRef.current.style.transform = `translate(${offsetL}px, 0)`;
    });
  }, []);

  const getClientHeight = () => {
    return document.documentElement.clientHeight;
  };
  const getClientWidth = () => {
    return document.documentElement.clientWidth;
  };
  // 重置模态框居中位置
  const generateModalPosition = () => {
    // 如果配置居中，则调整left, top
    const documentElementWidth = document.documentElement.clientWidth;
    const documentElementHeight = document.documentElement.clientHeight;
    const tabsContentHeight = domUtils.closest(domRef.current as HTMLElement, '.tabs-content')?.clientHeight ?? 45;
    const mainPageHeight = getClientHeight() - tabsContentHeight;

    // fullHeightOnInit
    let domWidth = typeof props.width === 'number' ? (props.width ?? (domRef.current?.clientWidth ?? documentElementWidth)) : props.width;
    if (typeof domWidth === 'string') {
      const matchUnit = (['%', 'vw'].filter((item) => domWidth.includes(item))[0] ?? '');
      const [ratio, unit] = domWidth.split(matchUnit);
      domWidth = documentElementWidth * Number(ratio) * 0.01;
    }
    //  如果配置了初始化占满，则初始化的时候占满高度
    const domHeight = fullHeightOnInit ? mainPageHeight : (domRef.current?.clientHeight < (domWidth ?? 0)) ? minHeight : (domRef.current?.clientHeight ?? documentElementHeight);
    const Modalbody = domRef.current?.querySelector('.ant-modal-body') as HTMLElement
    if (Modalbody?.style && resizeable) {
      Modalbody.style.height = `${domHeight - titleDomHigh.current}px`
    }
    const left = (documentElementWidth - (domWidth ?? 0)) / 2;
    const top = (documentElementHeight - domHeight) / 2;
    const leftOffset = left < 0 ? 0 : left;
    const topOffset = fullHeightOnInit ? tabsContentHeight : (top < 0 ? 0 : top > domHeight ? (top / 2) : top);
    if (domRef?.current?.style) {
      // domRef.current.style.transform = ''
      domRef.current.style.width = `${domWidth}px`;
    }
    setPosition({ x: leftOffset, y: topOffset });

    // const BoundClientRect = domRef.current?.getBoundingClientRect()
    setResizableWidth(domWidth as number);
    setResizableHeight(domHeight as number);
    if (cacheConfigKey) {
      // 缓存弹窗配置
      requestAnimationFrame(() => {
        const configs = {
          x: leftOffset,
          y: topOffset,
          width: domWidth,
          height: domHeight,
        }
        configs['transform'] = domRef.current.style.transform;
        cacheModalConfig(configs);
      });
    }
  };
  // 配置缓存模态框
  const generateCachedModalPosition = (configs: string = '') => {
    try {
      const parsedConfigs = JSON.parse(configs);
      const { x, y, width, height, transform = '' } = parsedConfigs as ICacheDialog;
      setPosition({ x, y: y < 0 ? 0 : y });
      const Modalbody = domRef.current?.querySelector('.ant-modal-body') as HTMLElement;
      const isMinWidth = width === minWidth;
      if (Modalbody?.style && resizeable) {
        Modalbody.style.height = `${height - titleDomHigh.current}px`;
        Modalbody.classList[isMinWidth ? 'add' : 'remove']?.('isMinWidth');
      }
      // const BoundClientRect = domRef.current?.getBoundingClientRect()
      setResizableWidth(width as number);
      setResizableHeight((props.minHeight && (height < props.minHeight) ? props.minHeight : height) as number);

      requestAnimationFrame(() => {
        if (transform?.length) {
          domRef.current.style.transform = transform;
        }
      });
    } catch {
      // 如果无法初始化成功，则初始化配置
      generateModalPosition();
    }
  };
  // 缓存模态框配置
  const cacheModalConfig = (configs: ICacheDialog) => {
    if (cacheConfigKey?.length) {
      localStorage.setItem(cacheConfigKey, JSON.stringify(configs));
    }
  }
  const extOpt = useMemo(() => {
    if (isMobile() && mode == 'mobile') {
      return { footer: footDom() };
    } else {
      return {};
    }
  }, [isMobile(), mode]);

  const getIsDragDisabled = useMemo(() => {
    const result = (drag && ((pinRight && pinToRight) || isFixRight.current || fixRight || maxSize || modalStore.modalId !== modalId)) || !drag;
    return result;
  }, [modalStore.modalId, isFixRight.current, fixRight, maxSize, pinToRight]);
  const handleReShowDialog = (e) => {
    if (isMiniTitleDragging) return;
    showDialog(e);
  }
  const handlePinRightSize = (pin: boolean) => {
    document.body.dispatchEvent(
      new Event(pin ? ResizeEvent.RESET_MAIN_PAGE_WIDTH + pageContentId : ResizeEvent.STOP_RESIZE_AFTER_PIN + pageContentId)
    );
  }
  const handlePinRight = () => {
    const modalDom = domUtils.closest(domRef.current as HTMLDivElement, '.ant-modal-wrap.drag-dialog');
    const mainPage = domUtils.closest(domRef.current as HTMLElement, '.main-page-content');
    if (modalDom) {
      const finalIndex = 999;
      modalDom.style.zIndex = finalIndex;
      setModalZIndex(finalIndex);
    }
    manualFix.current = true;
    // setResizableWidth(450);
    setPinToRight((pin) => {
      // 如果一个主页面有多个表格存在固定在右侧的弹窗，则不做恢复宽度处理
      if (mainPage && pin) {
        const hasNotReset = mainPage.querySelectorAll('.resize-container.dialog-pin-right').length > 1;
        if (!hasNotReset) {
          handlePinRightSize(pin);
        }
      } else {
        handlePinRightSize(pin);
      }
      return !pin
    });
    toggleDialogFixRight();
    setMaxSize(false);

  }

  if (!dialogVisible) return <></>
  return (
    <div className="fl-dialog-wrapper" onContextMenu={e => { e.stopPropagation() }}
      onKeyDown={(e) => {
        if (keyboard) {
          if (keyHandle) {
            keyHandle(e as any);
          } else {
            onKeyDown(e);
          }
        }
      }}
    >
      <div ref={(ref) => dragModalRef.current = ref} className='fl-dialog-box'>
        {
          (props.showMinTitle ? (
            <div className='mini-dialog-wrap'
              style={{ zIndex: modalZIndex }}
            >
              <Rnd
                ref={ref => minTitleDomRef.current = ref}
                className={['mini-dialog-drag-box', props.hide ? 'show' : ''].join(' ')}
                enableResizing={false}
                disableDragging={!miniTitleWrapperClassName}

                onDrag={onTitleDragStart}
                onDragStop={onTitleDragStop}
                dragHandleClassName={miniTitleWrapperClassName}
              >
                <div className={['min-dialog', miniTitleWrapperClassName].join(' ')}
                  ref={titleMinDom}
                >
                  <div className="disabled-move-title">{title || '弹窗'}</div>
                  <div className="tools-bar">
                    {props.onHide ? <div onClick={handleReShowDialog} className='btn-hide tool-btn'>
                      {hiddenBtn ?? <Icon icon="window-restore" className="tool-btn" />}
                    </div> : null
                    }
                    {((mode === 'mobile' || hideTitle) ? false : closable) ? <div onClick={btnCancel} className='btn-close tool-btn'>
                      <Icon icon="close" className="tool-btn" /></div> : null}
                  </div>
                </div>
              </Rnd>
            </div>
          ) : null)
        }
        <Modal
          {...props}
          {...extOpt}
          wrapClassName='drag-dialog'
          style={{ ...(props.style ?? {}), zIndex: modalZIndex }}
          closeIcon={null}
          className={['fl-modal', className, mode === 'mobile' ? 'mb-dialog' : 'pc-dialog'].join(' ')}
          getContainer={props.getContainer || document.body}
          width={mode == 'mobile' ? '75%' : props.width}
          closable={false}
          onCancel={btnCancel}
          keyboard={keyboard}
          open={dialogVisible && !props.hide}
          destroyOnClose={false}
          modalRender={(modal) => {
            return (
              <Rnd
                ref={(ref) => rndMainRef.current = ref}
                className={["resize-container", fixRight ? 'dialog-fix-right' : '', !resizeable ? 'height-auto' : '', stickyRight ? 'sticky-right' : '', pinToRight ? 'dialog-pin-right' : ''].join(' ')}
                style={{ ...{ 'pointerEvents': resizeable ? 'auto' : 'none' }, ...(fixRight && !pinRight ? fixRightStyleRef.current : {}), ...maxSize ? maxSizeStyleRef.current : {} }}
                enableResizing={((fixRight && !pinRight) || maxSize) ? {
                  // left: fixRight
                } : pinRight && (pinToRight || isFixRight.current) ? {
                  top: false,
                  right: false,
                  bottom: false,
                  left: false,
                  topRight: false,
                  bottomRight: false,
                  bottomLeft: false,
                  topLeft: false,

                } : resizeable ? {
                  top: true,
                  right: true,
                  bottom: true,
                  left: true,
                  topRight: true,
                  bottomRight: true,
                  bottomLeft: true,
                  topLeft: true,
                } : false}
                disableDragging={getIsDragDisabled}
                minWidth={minWidth || 200}
                maxWidth={maxSize ? '100vw' : (props.maxWidth ?? getClientWidth())}
                // 这个时算上了标题
                minHeight={minHeight}
                maxHeight={maxSize ? 'calc(100vh - 45px)' : getClientHeight()}
                bounds={bounds}
                dragHandleClassName="dialog-title"
                resizeHandleWrapperClass="handle-box"
                // 拖拽弹窗只有改这个才有用
                size={{ width: resizableWidth, height: resizableHeight }}
                position={position}
                // onDragStart={onDragStart}
                onDrag={onDrag}
                onDragStop={onDragStop}
                onResize={onResize}
                onResizeStop={onResizeStop}
              // onMouseLeave={onMouseLeave}

              >
                {modal}
              </Rnd>
            );
          }}
          title={
            hideTitle ? null : (
              <div
                style={{ cursor: (maxSize || fixRight) ? 'auto' : undefined }}
                className="dialog-title"
                onMouseEnter={() => {
                  modalStore?.defineModalId?.(modalId)
                }}
                onDragOver={(e) => e.preventDefault()}
                ref={titleDom}
              >
                <div className="disabled-move-title">{title}</div>
                <div className="tools-bar" onMouseDown={(e) => e.stopPropagation()}>
                  <div>
                    {(props.pinRight) ? (pinToRight ? <PushpinFilled onClick={handlePinRight} /> : <PushpinOutlined onClick={handlePinRight} />) : null}
                    {(props.setFixRight && !maxSize) ? (fixRight ? <VerticalRightOutlined onClick={(e) => { manualFix.current = true; toggleDialogFixRight() }} style={{ cursor: 'pointer' }} /> : <VerticalLeftOutlined onClick={(e) => { manualFix.current = true; toggleDialogFixRight() }} style={{ cursor: 'pointer' }} />) : null}</div>
                  {(props.setMaxSize) ? (<div> {maxSize ? (
                    <Icon className="icon tool-btn" icon="compress-alt" onClick={toggleMaxSize}></Icon>
                  ) : <Icon className="icon tool-btn" onClick={toggleMaxSize} icon="expand-alt"></Icon>} </div>) : null}
                  <div>{props.onHide ? <MinusOutlined onClick={hideDialog} style={{ cursor: 'pointer' }} /> : null}</div>

                  {((mode === 'mobile' || hideTitle) ? false : closable) ? <div onClick={btnCancel} style={{ cursor: 'pointer' }}>
                    <Icon icon="close" className="icon tool-btn" /></div> : null}
                </div>
              </div>
            )
          }
        >
          <div
            ref={contentRef}
            style={{ height: '100%', width: '100%' }}
          >
            {children}
          </div>
        </Modal>

      </div>
    </div>
  );
}));

// @inject('modalStore')
// @observer
// class Dialog extends React.Component<Partial<IDialogProps>> {
//   render() {
//     return (
//       <div className="fl-dialog-wrapper" onContextMenu={e => { e.stopPropagation() }}>
//         <FLModal {...this.props as IDialogProps} />
//       </div>
//     )
//   }
// }
export default FLModal;