/* eslint-disable react-hooks/exhaustive-deps */
import React, { useMemo, useRef, useState, useCallback, useEffect } from 'react';
import MoveContent from '../MoveContent';
import { getRectImagePath } from './loadCaptureRectImage';
import { computedBound } from './dragBound';
import { customContextMenu, computedRectScale, computedRoiRectScale, cloneImageNode, computedDrawAreaScale } from './utils';
import useDraw from './useDraw';
import { resizeObserver } from '@zenview/micro-utils';
import Tools from './component/Tools';
import DrawRect from './component/DrawRect';
import WheelScale from './component/WheelScale';
import DefaultRects from './component/DefaultRects';
import { isFunction } from 'lodash';
import './index.less';

function Picture({ drawArea, roiRects, className = '', width, height, minHeight = 300, disabledDrag = false, imagePath, rects = [], imgDownload, isOpenSelect = false, disabledDrawMenu = false, menus = [], onClickRect, onMenuClick, children, hasTool = true, fullScreenEle = null }) {
  const [state, setState] = useState({ x: 0, y: 0, rotate: 0, scale: 1, baseXOrY: 'x', forceUpdateKey: Date.now(), fullScreenStatus: false });
  const layoutRef = useRef(null);
  const moveActionRef = useRef(null);
  const domImgRef = useRef(null);
  const imageSourceRef = useRef(null);
  const canvasRef = useRef(null);
  const [selectArea, isEnd] = useDraw(layoutRef.current, isOpenSelect);
  const loadImageSuccess = useCallback(async (flag) => {
    imageSourceRef.current = await cloneImageNode(domImgRef.current);
    const { width, height } = domImgRef.current;
    setState((old) => ({ ...old, forceUpdateKey: Date.now(), baseXOrY: width > height ? 'x' : 'y', fullScreenStatus: !!flag }));
  }, []);
  /**
   * 设置图片缩放
   */
  const setScale = useCallback(
    (changeValue) => {
      const currentValue = state.scale;
      if (currentValue === 3 && changeValue > 0) {
        return;
      }
      if (currentValue === 1 && changeValue < 0) {
        return;
      }
      let scale = currentValue + changeValue;
      if (scale > 3) {
        scale = 3;
      }
      if (scale < 1) {
        scale = 1;
      }
      setState((old) => ({ ...old, scale }));
    },
    [state.scale]
  );

  /**
   * 设置图谱旋转
   */
  const setRotate = useCallback(
    (changeValue) => {
      const currentValue = state.rotate;
      setState((old) => ({ ...old, rotate: currentValue + changeValue }));
    },
    [state.rotate]
  );

  /**
   * 重置图片位置
   */
  const resetPicture = useCallback((event) => {
    event.stopPropagation(event);
    setState((old) => ({ ...old, scale: 1, rotate: 0 }));
    moveActionRef.current.updatePosition({ x: 0, y: 0 });
  }, []);

  /**
   * 拖拽更新位置
   */
  const onDragChange = useCallback(({ x, y }) => setState((old) => ({ ...old, x, y })), []);

  /**
   * 拖拽结束更新位置，计算边界
   */
  const onDragEnd = useCallback(
    (_, currrentPosition) => {
      const { scale, rotate } = state;
      if (!layoutRef.current) {
        return;
      }
      let position = computedBound(layoutRef.current, currrentPosition, scale, rotate);
      if (position) {
        moveActionRef.current.updatePosition(position);
      }
    },
    [state]
  );

  /**
   * 获取结构化的小图(base64)
   */
  const getRectImage = useCallback(
    (rect) => {
      let { scale, rotate, x, y } = state;
      return getRectImagePath(imageSourceRef.current, domImgRef.current, rect, { scale, rotate, x, y });
    },
    [state]
  );

  useEffect(() => {
    let timer = null;
    const fn = () => {
      clearTimeout(timer);
      timer = setTimeout(() => {
        setState((old) => ({ ...old, forceUpdateKey: Date.now() }));
      }, 200);
    };
    const dom = layoutRef.current;
    resizeObserver.createResizeObserver(dom, fn);
    return () => {
      resizeObserver.unResizeObserver(dom);
    };
  }, []);

  const scaleRects = useMemo(() => computedRectScale({ imageSource: imageSourceRef.current, domImg: domImgRef.current, rects }), [rects, state.forceUpdateKey]);
  const scaleDrawArea = useMemo(() => computedDrawAreaScale({ imageSource: imageSourceRef.current, domImg: domImgRef.current, drawArea }), [drawArea, state.forceUpdateKey]);


  const scaleRoiRects = useMemo(() => computedRoiRectScale({ imageSource: imageSourceRef.current, domImg: domImgRef.current, roiRects }), [roiRects, state.forceUpdateKey])


  const isEmpty = useMemo(() => selectArea.includes(0), [selectArea]);
  const { x, y, scale, rotate, baseXOrY } = useMemo(() => state, [state]);

  const renderOptions = {
    isEnd,
    isOpenSelect,
    selectArea,
    getRectImage: getRectImage,
    containerEle: layoutRef.current,
    fullScreenStatus: state.fullScreenStatus,
  };

  const drawRoi = (rectItem) => {
    const { rect, color = '#127aff' } = rectItem
    if (rect && rect.length) {
      const canvas = canvasRef.current
      const ctx = canvas.getContext('2d');
      canvas.width = domImgRef.current?.width
      canvas.height = domImgRef.current?.height
      // 多边形的顶点坐标相对于左下角原点的偏移量  
      ctx.beginPath();
      ctx.lineWidth = 2;
      ctx.setLineDash([5, 10])
      ctx.strokeStyle = color; // 设置边线颜色rgba(151, 71, 255); ,rgba(211 ,85 ,167);
      ctx.fillStyle = `${color}1a`; // 设置填充颜色

      rect.forEach((v, k) => {
        if (k === 0) {
          ctx.moveTo(v[0], v[1]); // 起点在左下角，向右上方移动到第一个顶点  
        } else {
          ctx.lineTo(v[0], v[1]); // 起点在左下角，向右上方移动到第一个顶点  
        }
      })
      ctx.closePath();
      ctx.stroke();
      ctx.fill();
    }
  }
  useEffect(() => {
    const canvas = canvasRef.current;
    const ctx = canvas.getContext('2d');
    ctx.clearRect(0, 0, canvas.width, canvas.height);

    [...scaleRoiRects, scaleDrawArea].forEach((item) => { //管网roi和图库roi合并成一个数组,同时绘制,绘制前先清空画布
      drawRoi(item)
    })

  }, [canvasRef, scaleRoiRects, scaleDrawArea, domImgRef.current?.width, domImgRef.current?.height])

  // useEffect(() => {
  //   drawRoi(scaleDrawArea)

  // }, [canvasRef, scaleDrawArea, domImgRef.current?.width, domImgRef.current?.height])
  return (
    <>
      <div className={`picture-view-layout ${className}`} style={{ width: width || '100%', height: height || '100%', minHeight }} ref={layoutRef} onContextMenu={customContextMenu}>
        <MoveContent
          className="picture-move-layout"
          disabled={isOpenSelect || disabledDrag}
          position={{ x, y }}
          ref={moveActionRef}
          onDragChange={onDragChange}
          onDragEnd={onDragEnd}
          style={{ minHeight: minHeight }}
          size={{ width: width ? 'max-content' : '100%', height: height ? 'max-content' : '100%' }}
        >
          <div style={{ transform: `scale(${scale}) rotate(${rotate}deg)` }}>
            <img alt="" ref={domImgRef} crossOrigin="anonymous" style={{ maxWidth: baseXOrY === 'x' ? width || '100%' : 'unset', maxHeight: baseXOrY === 'x' ? 'unset' : height || '100%' }} draggable={false} src={imagePath} key={imagePath} onLoad={loadImageSuccess} />
            {
              !isOpenSelect ? <canvas style={{ width: domImgRef.current?.width, height: domImgRef.current?.height }} ref={canvasRef} className="scale-draw-area-canvas"  ></canvas> : null
            }
            {!isEmpty ? (
              <DrawRect rect={selectArea} onMenuClick={onMenuClick} getRectImage={getRectImage} menus={menus} canRenderMenu={isEnd && !disabledDrawMenu && menus.length > 0} containerDom={layoutRef.current} />
            ) : !isOpenSelect ? (
              <DefaultRects rects={scaleRects} onClickRect={onClickRect} getRectImage={getRectImage} containerDom={layoutRef.current} />
            ) : null}
          </div>
        </MoveContent>
        {hasTool && <Tools setScale={setScale} setRotate={setRotate} scale={scale} containerEle={fullScreenEle || layoutRef.current} resetPicture={resetPicture} imgDownload={imgDownload} fullScreenChange={loadImageSuccess} />}
        <WheelScale setScale={setScale} dom={layoutRef.current} />
      </div>
      {isFunction(children) && children(renderOptions)}
    </>
  );
}

export default Picture;
