import React, { useEffect, ReactElement, useState, useRef, useImperativeHandle } from 'react';
import classNames from 'classnames';
import {
  get,
  pick,
  isNull,
  generateImg,
  dataURLToBlob,
  getTransforms,
  addEventListenerWrapper,
  getFileByRect
} from '@zhst/func';
import Align from 'rc-align';
import { Empty, AttachImage } from '..';
import { type Rect, type IScreenshotButtonProp, type AlignType } from '@zhst/types'
import {
  Cropper,
  Viewer,
  EVENT_VIEWER_TRANSFORM_CHANGE,
  EVENT_VIEWER_READY,
  EVENT_CROP_START,
  EVENT_CROP_END,
} from '../ImageEditor';
import BtnGroup from './components/BtnGroup';
import './index.less'
import { defaultAlignOption, CROP_TYPE } from '../utils/constants'
import {
  getOdRect,
  IOdObject,
  getExtendRect,
  getTransformRect,
  getRotateImg, } from './bigImagePreviewHelper'

const componentName = `zhst-image__img-view`;

export interface ViewOption {
  /* 图片url */
  image?: string | HTMLImageElement;

  /* 缩放灵敏度(0,1],default: 0.1 */
  wheelZoomRatio?: number;

  /*
   * 是否允许缩放
   * @default: true
   */
  scaleAble?: boolean;

  /*
   * 是否允许拖拽
   * @default: true
   */
  dragAble?: boolean;

  /*
   * fit scale 作为 最小缩放
   * @default: false
   */
  fitScaleAsMinScale?: boolean;
}

export interface ImgViewProps extends React.HTMLAttributes<HTMLElement> {
  data: {
    url?: string
    imageKey: string
    attachImg?: Array<{ label: string; url: string }>;    // 缩略图列表
    odRect?: Rect
    score?: number
    objects?: IOdObject
  }
  showAttachImgLabel?: boolean;          // 是否显示缩略图
  showOpt?: boolean; // 是否显示操作面板
  width?: string | number;    // 画布宽度
  height?: string | number;   // 画布高度
  /* 截图渲染 */
  screenshotButtonAlign?: AlignType;
  screenshotButtonRender?: (screenshotButtonProp: IScreenshotButtonProp) => ReactElement;
  hideLeftTopBtn?: boolean;
  onDraw?: (obj: {
    rectList: any;
    extendRectList: {
        x: number;
        y: number;
        w: number;
        h: number;
    }[];
    selectIndex: number;
    imgKey: string;
  }) => void
  showScore?: boolean // 是否显示相似度
  viewOption?: ViewOption;
  onRectSelect?: (data: {
    rectList: any[];
    extendRectList: any[];
    selectIndex: number;
    imgKey: string;
  }) => void
  type?: 'CUSTOM' | 'AUTO'
  hideTypeBtns?: boolean
  customEmpty?: any
}
export interface ImgViewRef {
  /* 图片实例 */
  imgInsRef: React.MutableRefObject<any>;
  /* 切换编辑模式 */
  setShowCrop: React.Dispatch<React.SetStateAction<boolean>>;
}

const cropBtnDataSource = [
  {
    key: 'close',
    icon: 'icon-danchuangguanbi',
    title: '退出',
  },
  {
    key: 'autoCrop',
    icon: 'icon-zidong',
    title: '智能框选',
  },
  {
    key: 'customCrop',
    icon: 'icon-shoudong',
    title: '手动框选',
  },
];

const operateBtnDataSource = [
  {
    key: 'zoomOut',
    icon: 'icon-fangda',
    title: '放大',
  },
  {
    key: 'zoomIn',
    icon: 'icon-suoxiao',
    title: '缩小',
  },
  {
    key: 'reset',
    icon: 'icon-zhongzhi3',
    title: '重置图片',
  },
];

export const BigImagePreview = React.forwardRef<ImgViewRef, ImgViewProps>((props, ref) => {
  const {
    width,
    height,
    showScore = false,
    data,
    showOpt = false,
    showAttachImgLabel = true,
    screenshotButtonAlign = defaultAlignOption,
    screenshotButtonRender = () => <div style={{ color: '#fff', width: '80px', top: 0, fontSize: 12 }}>回调DOM</div>,
    hideLeftTopBtn = true,
    onDraw,
    viewOption = {},
    type,
    hideTypeBtns,
    customEmpty,
  } = props;
  const {
    imageKey,
    attachImg,
    odRect,
    score,
    objects = [],
  } = data
  const imgContainerRef = React.useRef(null);

  // ============================= viewer  =========================
  const imgInsRef = useRef<any>(null);
  const [isImgReady, setIsImgReady] = useState(false);

  useEffect(() => {
    if (!imgContainerRef?.current) return;
    const handleReady = addEventListenerWrapper(imgContainerRef.current, EVENT_VIEWER_READY, () => {
      setIsImgReady(true);
    });
    const handleTransformChange = addEventListenerWrapper(
      imgContainerRef.current,
      EVENT_VIEWER_TRANSFORM_CHANGE,
      () => {
      }
    );
    imgInsRef.current = new Viewer(imgContainerRef.current, {
      ...viewOption,
      fitScaleAsMinScale: true,
      image: generateImg(imageKey),
    });
    return () => {
      handleReady?.remove();
      handleTransformChange?.remove();
      imgInsRef?.current?.destroy?.();
      imgInsRef.current = null;
    };
  }, [imageKey]);

  // ============================= viewer操作按钮 =========================
  const handleOptClick = (v: string) => {
    switch (v) {
      case 'zoomOut':
        imgInsRef?.current?.scaleTo?.(0.1);
        break;
      case 'zoomIn':
        imgInsRef?.current?.scaleTo?.(-0.1);
        break;
      case 'reset':
        imgInsRef?.current?.reset?.(-0.1);
        break;
    }
  };

  // ============================= cropper  =========================
  // 手动截图相关参数
  const cropInsRef: any = useRef(null);
  const [showCrop, setShowCrop] = useState(showOpt);
  const [cropType, setCropType] = useState(type || CROP_TYPE['AUTO']);

  // 自动截图相关参数
  const [odList, setOdList] = useState<any>([]);
  const [extendOdList, setExtendOdList] = useState([]);
  const [selectRectId, setSelectRectId] = useState(null);

  // 定位按钮相关参数
  const alginContainerRef: any = useRef(null);
  const alignRef: any = useRef(null);
  const [cropRect, setCropRect] = useState<Rect | null>(null);

  // 选中的版本号
  const [selectAlgorithmVersion, setSelectAlgorithmVersion] = useState(null);
  const handlerCropStartRef: any = useRef(null);
  const handlerCropEndRef: any = useRef(null);
  const handleShapeSelectRef: any = useRef(null);

  useEffect(() => {
    initData(objects)
    return () => {
      imgInsRef.current?.clearShape?.();
      handlerCropStartRef.current?.remove();
      handlerCropEndRef.current?.remove();
      handleShapeSelectRef.current?.remove();
      cropInsRef?.current?.destroy?.();
      cropInsRef.current = null;
    };
  }, [isImgReady, showCrop, cropType, imageKey]);

  // 初始化页面的绘制矩形
  const initData = (_objects: IOdObject | never[]) => {
    const imgIns = imgInsRef.current;
    const _odRect = odRect
    //清理crop
    setCropRect(null);
    if (!isImgReady) return;
    if (!showCrop) {
      imgIns?.addShape?.({
        x: get(_odRect, 'x', 0),
        y: get(_odRect, 'y', 0),
        w: get(_odRect, 'w', 0),
        h: get(_odRect, 'h', 0),
        selectAble: false,
      });
      return;
    }

    // 自动模式
    if (cropType === CROP_TYPE['AUTO']) {
      const handleGetOD = (odList: any) => {
        const imgSize = imgIns.getImgSize();
        const shapeList = odList.map((rect: { [x: string]: any; algorithmVersion: any; }) => ({
          ...rect,
          selectAble: true,
          id: ['id'],
          algorithmVersion: rect.algorithmVersion,
        }));
        imgIns.replaceShape(shapeList);
        //顺便吧扩展框拿到
        const extendRect = shapeList.map((rect: { algorithmVersion: string; }) => {
          // @ts-ignore
          const _extendRect = getExtendRect(rect, imgSize.w, imgSize.h, rect.algorithmVersion);
          return { ...rect, ..._extendRect };
        });
        setExtendOdList(extendRect);
        imgIns.replaceShape(shapeList);
        // 框选监听事件
        handleShapeSelectRef.current = addEventListenerWrapper(imgContainerRef.current, 'shape-select', async (e: { detail: any; }) => {
          const id = e.detail;
          setSelectRectId(id);
          const selectShape = shapeList.find((v: { [x: string]: any; }) => v['id'] === id);
          console.log('selectShape', selectShape,)
          if (selectShape) {
            setSelectAlgorithmVersion(selectShape['algorithmVersion']);
            //换算成屏幕坐标
            const axisRect = imgIns.imgRectAxisToCanvasAxisRect(selectShape);
            const rect = {
              x: axisRect.x2 > axisRect.x ? axisRect.x : axisRect.x2,
              y: axisRect.y2 > axisRect.y ? axisRect.y : axisRect.y2,
              w: Math.abs(axisRect.x2 - axisRect.x),
              h: Math.abs(axisRect.y2 - axisRect.y),
            };
            setCropRect(rect);
            onDraw?.({ rectList: [rect], extendRectList: [rect], imgKey: imageKey, selectIndex: id })
          } else {
            // @ts-ignore
            setCropRect(null);
          }
        });
      };
      // @ts-ignore
      const rect = getOdRect({ objects: _objects })
      setOdList(rect);
      handleGetOD(rect);
    }

    // 手动模式
    if (cropType === CROP_TYPE['CUSTOM']) {
      // 手动框选状态预先清除imgIns
      imgIns?.clearShape?.();
      handlerCropStartRef.current = addEventListenerWrapper(imgContainerRef.current, EVENT_CROP_START, () => {
        setSelectAlgorithmVersion(null);
        setCropRect(null);
      });
      handlerCropEndRef.current = addEventListenerWrapper(imgContainerRef.current, EVENT_CROP_END, async (event: { detail: any; }) => {
        const data = event.detail;
        setSelectAlgorithmVersion(null);
        const _rect = {
          x: data.left,
          y: data.top,
          w: data.width,
          h: data.height,
        }
        setCropRect(_rect);
        const _cropData = await getCropInfo({ type: cropType, rect: _rect })
        onDraw?.(_cropData)
        alignRef?.current?.forceAlign?.();
      });
      cropInsRef.current = new Cropper(imgContainerRef.current, {
        showMask: true,
        type: 'arrow',
        viewer: imgIns,
      });
    }
  }

  //  获取框选的截图框信息
  const getCropInfo = async (opt: { type: string; rect: Rect }) => {
    const { type, rect } = opt
    const cropType = type;
    const cropRect = rect;
    const imgIns = imgInsRef.current;
    const transform = imgIns.targetTransform;
    let newImgKey = imageKey;
    let rectList: any = [];
    let extendRectList = [];
    let selectIndex = 0;
    switch (cropType) {
      case CROP_TYPE['AUTO']:
        const shapes = imgIns.getSelectShape();
        const shapeIds = shapes.map((v: { [x: string]: any; }) => v['id']);
        rectList = odList
          .filter((v: { [x: string]: any; }) => shapeIds.includes(v['id']))
          .map((item: any) => {
            if (
              item.algorithmVersion === 'OBJECT_TYPE_FACE' ||
              item.objectType === 'OBJECT_TYPE_FACE'
            ) {
              if (!isNull(item.extendBox)) {
                return {
                  ...item,
                  w: get(item, 'extendBox.w'),
                  h: get(item, 'extendBox.h'),
                  x: get(item, 'extendBox.x'),
                  y: get(item, 'extendBox.y'),
                };
              }
            } else {
              return item;
            }
          });
        extendRectList = extendOdList
          .filter((v) => shapeIds.includes(v['id']))
          .map((v) => pick(v, ['x', 'y', 'w', 'h', 'algorithmVersion', 'id']));
        selectIndex = rectList.findIndex((v: { [x: string]: null; }) => v['id'] === selectRectId);
        break;
      default:
        //获取旋转过的坐标
        // @ts-ignore
        const newRect = getTransformRect(imgIns.image, transform, cropRect);
        //判断是不是旋转过
        if (get(transform, 'rotate', 0) % 360 != 0) {
          const data = getRotateImg(imgIns.image, get(transform, 'rotate', 0)) as any;
          //在画布上画旋转后的图片
          newImgKey = data as any;
        }
        rectList.push(newRect);
        extendRectList.push(newRect);
        break;
    }
    //扩展框获取imgkey
    await Promise.all(
      extendRectList.map(async (rect, index) => {
        const file = await getFileByRect(imgIns.image, rect);
        const imgKey = file;
        extendRectList[index] = { ...rect, imgKey };
      })
    );
    //人脸图获取矫正图
    await Promise.all(
      rectList.map(async (rect: { [x: string]: any; }, index: string | number) => {
        const faceCorrectImage = rect['faceCorrectImage'];
        let faceCorrectImageKey;
        if (faceCorrectImage) {
          const base64 = `data:image/jpg;base64,${faceCorrectImage}`;
          const blobData = dataURLToBlob(base64);
          const file = new window.File([blobData], `${new Date().getTime()}`);
          faceCorrectImageKey = file
        }
        const newRect: any = {
          ...rect,
          ...(faceCorrectImageKey ? { faceCorrectImageKey } : {}),
        };
        delete newRect['faceCorrectImage'];
        rectList[index] = newRect;
      })
    );

    let data = {
      rectList,
      extendRectList,
      selectIndex,
      imgKey: newImgKey
    }

    return data;
  };

  // 操作界面判断
  const handleCropBtnClick = (v: string) => {
    switch (v) {
      case 'close':
        setShowCrop(false);
        break;
      case 'autoCrop':
        setCropType(CROP_TYPE['AUTO']);
        break;
      case 'customCrop':
        setCropType(CROP_TYPE['CUSTOM']);
        break;
    }
  };

  // ============================== Ref ===============================
  useImperativeHandle(ref, () => ({
    imgInsRef,
    setShowCrop,
    initData,
    getCropInfo,
  }));

  return (
    <div className={classNames(`${componentName}`)} style={{ height, width }}>
      {/*场景图大图 */}
      {imageKey ?
        <>
          <div
            className={classNames(
              `${componentName}-main`,
              cropType === CROP_TYPE['AUTO'] && `${componentName}-main--cursor`
            )}
            ref={imgContainerRef}
            // style={{ width: width, height: height }}
          />
          {/* 图片操作 */}
          {!hideLeftTopBtn && (
            <BtnGroup
              className={classNames(`${componentName}-opt`)}
              dataSource={operateBtnDataSource}
              onClick={handleOptClick}
              placement="left"
            />
          )}
          {!hideTypeBtns && showCrop && (
            <BtnGroup
              circle
              className={classNames(`${componentName}-crop-opt`)}
              dataSource={cropBtnDataSource}
              onClick={handleCropBtnClick}
              selectKey={cropType === CROP_TYPE['AUTO'] ? 'autoCrop' : 'customCrop'}
            />
          )}
          {showCrop && cropRect && screenshotButtonRender && (
            <>
              <div
                ref={alginContainerRef}
                className={classNames(`${componentName}-align`)}
                style={Object.assign(
                  {
                    width: cropRect.w,
                    height: cropRect.h,
                  },
                  getTransforms({
                    translateX: cropRect.x,
                    translateY: cropRect.y,
                  })
                )}
              ></div>
              <Align
                ref={alignRef}
                monitorWindowResize
                align={screenshotButtonAlign}
                target={function () {
                  return alginContainerRef.current;
                }}
              >
                {screenshotButtonRender({
                  model: 'IMAGE',
                  // @ts-ignore
                  getCropInfo,
                  setShowCrop,
                  cropType,
                  selectAlgorithmVersion,
                })}
              </Align>
            </>
          )}
          {/* 场景图小图 */}
          {attachImg?.length && !showCrop &&  (
            <AttachImage
              showAttachImgLabel={showAttachImgLabel}
              data={attachImg}
            />
          )}
          {(showScore || score) && <div
            style={{ bottom: 20 }}
            className={classNames(`${componentName}__face-score`)}
          >
            {`人脸质量分：${(Number(score) as number).toFixed(2)}`}
          </div>}
        </>
        :
        <div style={{ height: '100%', display: 'flex', justifyContent: 'center', alignItems: 'center' }}>
          {customEmpty || <Empty style={{ margin: 0 }} image={Empty.PRESENTED_IMAGE_SIMPLE} description="暂无数据" />}
        </div>
      }
    </div>
  );
});

BigImagePreview.displayName = 'BigImagePreview';

export default BigImagePreview;
