import React, { useEffect, useRef } from 'react'

import {
  CloseCircleOutlined,
  ZoomInOutlined,
  ZoomOutOutlined,
  ExpandOutlined,
  UndoOutlined,
  RedoOutlined
} from '@ant-design/icons'

import styles from '../css/Picture.module.scss'
enum EAction {
  缩小 = 1,
  放大,
  全屏,
  左旋,
  右旋
}
type IAction = EAction.缩小 | EAction.放大 | EAction.全屏 | EAction.左旋 | EAction.右旋

export interface IPicture {
  imgSrc: string | undefined // 图片
  visible: boolean
  onClose: () => void
}
const Picture: React.FC<IPicture> = props => {
  const { imgSrc, visible, onClose } = props

  const scaleRate = 1.2
  const minScale = 0.01
  const cacheRef = useRef({
    x: 0,
    y: 0,
    canMove: false
  })

  useEffect(() => {
    const eBody = document.querySelector('body') as HTMLBodyElement
    eBody.style.height = visible ? '100%' : ''
    eBody.style.width = visible ? '100%' : ''
    eBody.style.overflow = visible ? 'hidden' : ''
  }, [visible])
  const handleTouchBigImg = (e: React.MouseEvent<HTMLElement, MouseEvent>) => {
    e.stopPropagation()
  }
  const onAction = (action: IAction) => {
    const queryEle = document.querySelectorAll(`.picture-img-div .big-img`) as NodeListOf<HTMLElement>
    const ele = queryEle[0]
    const DEFAULT_SCALE = 1

    if (!ele) {
      return
    }

    if (ele.tagName.toLowerCase() !== 'img') {
      return
    }

    const { transform } = ele.style
    if (action === EAction.缩小) {
      const transformStyle = getTransform(transform, {
        type: 'scale',
        transformScale: s => Math.max(Number((s / scaleRate).toFixed(2)), minScale)
      })

      ele.style.transform = transformStyle
    }
    if (action === EAction.放大) {
      ele.style.transform = getTransform(transform, {
        type: 'scale',
        transformScale: s => {
          return s * scaleRate
        }
      })
    }
    if (action === EAction.全屏) {
      ele.style.transform = getTransform(transform, {
        type: 'scale',
        transformScale: () => DEFAULT_SCALE
      })

      ele.style.left = '50%'

      ele.style.top = '50%'
    }
    if (action === EAction.左旋) {
      ele.style.transform = getTransform(transform, {
        type: 'rotate',
        transformRotate: d => d - 90
      })
    }
    if (action === EAction.右旋) {
      ele.style.transform = getTransform(transform, {
        type: 'rotate',
        transformRotate: d => d + 90
      })
    }
  }
  const stopMove = (ele: HTMLImageElement, mx?: number, my?: number) => {
    cacheRef.current.canMove = false
    document.onmousemove = null
    document.onmouseup = null
    if (mx === null || mx === undefined || my === null || my === undefined) {
      return
    }
    // 盒子距离浏览器
    ele.style.left = `${mx - cacheRef.current.x}px`
    ele.style.top = `${my - cacheRef.current.y}px`
  }
  const onMouseOut = () => {
    // event.preventDefault();
    // event.stopPropagation();
    // const img = event.target;
    // stopMove(img);
  }

  const onMouseUp = (event: React.MouseEvent<HTMLImageElement, MouseEvent>) => {
    event.preventDefault()
    event.stopPropagation()
    const img = event.target as HTMLImageElement
    const mx = event.clientX
    const my = event.clientY
    stopMove(img, mx, my)
  }

  const onMouseDown = (event: React.MouseEvent<HTMLImageElement, MouseEvent>) => {
    event.preventDefault()
    event.stopPropagation()
    const img = event.target as HTMLImageElement
    const mx = event.clientX // 鼠标距离浏览器左
    const my = event.clientY // 鼠标距离浏览器上
    const bx = img?.offsetLeft // 盒子距离浏览器左
    const by = img?.offsetTop // 盒子距离浏览器上
    cacheRef.current.x = mx - bx // 实际盒子距离的浏览器左
    cacheRef.current.y = my - by // 实际盒子距离的浏览器上
    cacheRef.current.canMove = true
    // 注册鼠标移动事件处理函数
    document.onmousemove = e => {
      if (!cacheRef.current.canMove) {
        return
      }
      const _mx = e.clientX
      const _my = e.clientY
      // 盒子距离浏览器
      const left = `${_mx - cacheRef.current.x}px`
      const top = `${_my - cacheRef.current.y}px`
      img.style.left = left
      img.style.top = top
    }
    document.onmouseup = () => {
      stopMove(img)
    }
  }

  const getTransform = (
    transform: string,
    {
      type = 'rotate',
      transformScale,
      transformRotate
    }: {
      scaleRate?: number
      type: 'rotate' | 'scale'
      transformScale?: (scale: number) => number
      transformRotate?: (deg: number) => number
    }
  ) => {
    const rotateReg = /rotate\((.*)deg\)/
    const scaleReg = /scale\((.*)\)/

    const DEFAULT_SCALE = 1
    const DEFAULT_ROTATE = 0

    const deg = Number(transform.match(rotateReg)?.[1] || DEFAULT_ROTATE)
    const scale = Number(transform.match(scaleReg)?.[1] || DEFAULT_SCALE)

    const _scale = transformScale ? transformScale(scale) : scale
    const _deg = transformRotate ? transformRotate(deg) : deg

    if (type === 'rotate') {
      return scale !== 1
        ? `translate(-50%, -50%) rotate(${_deg}deg) scale(${scale})`
        : `translate(-50%, -50%) rotate(${_deg}deg)`
    }
    return deg ? ` translate(-50%, -50%) rotate(${deg}deg) scale(${_scale})` : `translate(-50%, -50%) scale(${_scale})`
  }
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  const mousewheel = (b: any) => {
    const queryImages = document.querySelectorAll(`.picture-img-div .big-img`) as NodeListOf<HTMLElement>
    const img = queryImages[0]
    if (img?.tagName.toLowerCase() !== 'img') {
      return
    }
    if (!img || !visible) {
      return
    }

    const { transform } = img.style

    let isDown = false

    if (b.wheelDelta) {
      isDown = b.wheelDelta < 0
    } else {
      isDown = b.detail > 0
    }

    img.style.transform = getTransform(transform, {
      type: 'scale',
      transformScale: s => (isDown ? Math.max(Number((s / scaleRate).toFixed(2)), minScale) : s * 1.2)
    })
  }

  const onContainerMouseOver = (event: React.MouseEvent<HTMLImageElement, MouseEvent>) => {
    event.preventDefault()
    event.stopPropagation()
    const ele = event.target
    if (ele && ele.addEventListener) {
      ele.addEventListener('DOMMouseScroll', mousewheel, false)
      ele.addEventListener('mousewheel', mousewheel, false)
    }
  }

  return visible ? (
    <div className={styles['picture-img-wrapper']} onClick={onClose} onMouseOver={onContainerMouseOver}>
      <div className="picture-modal-mask"></div>
      <div className="picture-modal-wrap">
        <div className="picture-img-div" onClick={handleTouchBigImg}>
          <div className="close-wrap" onClick={onClose} />
          <img
            src={imgSrc}
            alt="图片"
            className="big-img"
            onMouseUp={onMouseUp}
            onMouseDown={onMouseDown}
            onMouseOut={onMouseOut}
            draggable={false}
          />
        </div>
      </div>
      <CloseCircleOutlined className="picture-close" onClick={onClose} />

      <div className="picture-option-wrapper" onClick={handleTouchBigImg}>
        <ZoomOutOutlined className="picture-option-btn" onClick={onAction.bind(this, EAction.缩小)} />
        <ZoomInOutlined className="picture-option-btn" onClick={onAction.bind(this, EAction.放大)} />
        <ExpandOutlined className="picture-option-btn" onClick={onAction.bind(this, EAction.全屏)} />
        <UndoOutlined className="picture-option-btn" onClick={onAction.bind(this, EAction.左旋)} />
        <RedoOutlined className="picture-option-btn" onClick={onAction.bind(this, EAction.右旋)} />
      </div>
    </div>
  ) : null
}

export default Picture
