import { Image as AntdImage, ImageProps, ConfigProvider } from 'antd';
import React, {
  createContext,
  useCallback,
  useContext,
  useEffect,
  useState,
} from 'react';
import './index.less';
import classNames from 'classnames';
import { Icon } from '../Icon';
import errorIcon from './icons/error.png';
import { Modal } from 'antd';
import { GroupConsumerProps } from 'rc-image/lib/PreviewGroup';
import { useRequest } from 'ahooks';

// 提供回调函数给image
export const ImageGroupContext = createContext({
  beforeOpenPreview: (src: string) => {},
  changeImages: (src: string, isDelete = false) => {},
});

interface ImageExtraProps {}

const Image = (props: ImageProps & ImageExtraProps) => {
  const { getPrefixCls } = useContext(ConfigProvider.ConfigContext);
  const prefixCls = getPrefixCls('btri-image');

  const { beforeOpenPreview, changeImages } = useContext(ImageGroupContext);

  const { preview, src } = props;
  useEffect(() => {
    const resSrc = (typeof preview === 'object' && preview?.src) || src;
    changeImages(resSrc);
    return () => {
      changeImages(resSrc, true);
    };
  }, []);
  // 重新处理preview
  const [_previewVisible, setPreviewVisible] = useState(false);
  const getPreview = useCallback(() => {
    const basePreview = {
      visible: false,
      onVisibleChange: (e: boolean, pre) => {
        setPreviewVisible(e);
        typeof preview !== 'boolean' && preview?.onVisibleChange?.(e, pre);
      },
      mask: (
        <div
          className={classNames(`${prefixCls}-mask-content`)}
          onClick={() => {
            beforeOpenPreview(props.src);
          }}
        >
          <Icon iconName="PreviewOpen"></Icon>
          <div>预览</div>
        </div>
      ),
    };
    switch (preview) {
      case false:
        return false;
      case true:
        return basePreview;
      default:
        return { ...preview, ...basePreview };
    }
  }, [preview, props.src, beforeOpenPreview]);
  // previewImage状态变量
  const [_scale, setScale] = useState(1);
  const [_degree, setDegree] = useState(0);

  // 图片移动功能
  const [position, setPosition] = useState([0, 0]);
  const [margin, setMargin] = useState([0, 0]);
  const [isMoving, setIsMoving] = useState(false);
  const updatePosition = (pos: [number, number]) => {
    setPosition(prePos => {
      (prePos?.[0] || prePos?.[1]) &&
        setMargin(preMargin => {
          return [
            preMargin[0] + pos[0] - prePos[0],
            preMargin[1] + pos[1] - prePos[1],
          ];
        });
      return pos;
    });
    return new Promise<void>(resolve => {
      resolve();
    });
  };
  const { run } = useRequest(updatePosition, {
    throttleWait: 30,
  });

  useEffect(() => {
    if (!_previewVisible) {
      setMargin([0, 0]);
      setScale(1);
      setDegree(0);
    }
  }, [_previewVisible]);

  return (
    <>
      <AntdImage
        fallback={errorIcon}
        placeholder={
          <div
            className={classNames(`${prefixCls}-loading`)}
            style={props.style}
          >
            <Icon iconName="Loading" spin></Icon>
          </div>
        }
        {...props}
        className={classNames(`${prefixCls}-box`, props.className)}
        rootClassName={classNames(`${prefixCls}-root`, props.rootClassName)}
        preview={getPreview()}
      ></AntdImage>
      <Modal
        visible={_previewVisible}
        footer={null}
        bodyStyle={{ padding: 0, background: 'transparent', height: '100%' }}
        onCancel={() => {
          setPreviewVisible(false);
        }}
        style={{ background: 'transparent' }}
        width="100%"
        className={classNames(`${prefixCls}-preview`)}
        closeIcon={
          <div
            style={{
              width: '32px',
              height: '32px',
              borderRadius: '50%',
              background: 'var(--fill-4)',
              margin: '30px 0',
              display: 'flex',
              alignItems: 'center',
              justifyContent: 'center',
            }}
          >
            <Icon
              iconName="CloseSmall"
              style={{
                fontSize: '20px',
                color: 'var(--bg-2)',
              }}
            ></Icon>
          </div>
        }
        maskStyle={{
          background: '#050505',
          opacity: 0.6,
        }}
        centered
      >
        <div className={classNames(`${prefixCls}-preview-container`)}>
          <div
            style={{
              transform: `translate(${margin[0]}px, ${margin[1]}px)`,
              display: 'flex',
              alignItems: 'center',
              justifyContent: 'center',
              width: '100%',
              height: '100%',
            }}
          >
            <Image
              src={
                (typeof props.preview === 'object' && props.preview?.src) ||
                props.src
              }
              style={{
                maxHeight: '100%',
                maxWidth: '100%',
                transform: `scale(${_scale}) rotate(${_degree}deg)`,
                width: 'auto',
              }}
              preview={false}
              onMouseDown={() => {
                setIsMoving(true);
              }}
              onMouseUp={() => {
                setIsMoving(false);
                setPosition([0, 0]);
              }}
              onMouseMove={e => {
                isMoving && run([e.clientX, e.clientY]);
              }}
              draggable={false}
            ></Image>
          </div>
          <div className={classNames(`${prefixCls}-handle`)}>
            <Icon
              iconName="ZoomIn"
              onClick={() => {
                setScale(pre => pre + 1);
              }}
            ></Icon>
            <Icon
              iconName="ZoomOut"
              onClick={() => {
                setScale(pre => pre - 1 || 1);
              }}
            ></Icon>
            <Icon
              iconName="ImgLeft"
              onClick={() => {
                setDegree(pre => pre - 90);
              }}
            ></Icon>
            <Icon
              iconName="ImgRight"
              onClick={() => {
                setDegree(pre => pre + 90);
              }}
            ></Icon>
          </div>
        </div>
      </Modal>
    </>
  );
};

const PreviewGroup: React.FC<GroupConsumerProps> = props => {
  const { getPrefixCls } = useContext(ConfigProvider.ConfigContext);
  const prefixCls = getPrefixCls('btri-image-group');
  const { preview } = props;

  // previewImage状态变量
  const [_scale, setScale] = useState(1);
  const [_degree, setDegree] = useState(0);
  // 收集图片
  const [images, setImages] = useState<string[]>([]);
  // 展示序号
  const [_previewIndex, setPreviewIndex] = useState(0);

  // 重新处理preview
  const [_previewVisible, setPreviewVisible] = useState(false);
  const getPreview = useCallback(() => {
    const basePreview = {
      visible: false,
      onVisibleChange: (e: boolean, pre) => {
        setPreviewVisible(e);
        typeof preview !== 'boolean' && preview?.onVisibleChange?.(e, pre);
      },
      mask: (
        <div className={classNames(`${prefixCls}-mask-content`)}>
          <Icon iconName="PreviewOpen"></Icon>
          <div>预览</div>
        </div>
      ),
    };
    switch (preview) {
      case false:
        return false;
      case true:
        return basePreview;
      default:
        return { ...preview, ...basePreview };
    }
  }, [preview]);

  const switchPicture = useCallback(
    i => {
      setPreviewIndex(pre => (pre + i + images.length) % images.length);
    },
    [images],
  );

  // 图片移动功能
  const [position, setPosition] = useState([0, 0]);
  const [margin, setMargin] = useState([0, 0]);
  const [isMoving, setIsMoving] = useState(false);
  const updatePosition = (pos: [number, number]) => {
    setPosition(prePos => {
      (prePos?.[0] || prePos?.[1]) &&
        setMargin(preMargin => {
          return [
            preMargin[0] + pos[0] - prePos[0],
            preMargin[1] + pos[1] - prePos[1],
          ];
        });
      return pos;
    });
    return new Promise<void>(resolve => {
      resolve();
    });
  };
  const { run } = useRequest(updatePosition, {
    throttleWait: 30,
  });
  useEffect(() => {
    if (!_previewVisible) {
      setMargin([0, 0]);
      setScale(1);
      setDegree(0);
    }
  }, [_previewVisible]);

  return (
    <>
      <AntdImage.PreviewGroup {...props} preview={getPreview()}>
        <ImageGroupContext.Provider
          value={{
            beforeOpenPreview: src => {
              const index = images.findIndex(item => item === src);
              setPreviewIndex(index);
            },
            changeImages: (src, isDelete) => {
              if (isDelete) {
                setImages(pre => pre.filter(item => item === src));
              } else {
                setImages(pre => pre.concat(src));
              }
            },
          }}
        >
          {props.children}
        </ImageGroupContext.Provider>
      </AntdImage.PreviewGroup>
      <Modal
        visible={_previewVisible}
        footer={null}
        bodyStyle={{ padding: 0, background: 'transparent', height: '100%' }}
        onCancel={() => {
          setPreviewVisible(false);
        }}
        style={{ background: 'transparent' }}
        width="100%"
        className={classNames(`${prefixCls}-preview`)}
        closeIcon={
          <div
            style={{
              width: '32px',
              height: '32px',
              borderRadius: '50%',
              background: 'var(--fill-4)',
              margin: '30px 0',
              display: 'flex',
              alignItems: 'center',
              justifyContent: 'center',
            }}
          >
            <Icon
              iconName="CloseSmall"
              style={{
                fontSize: '20px',
                color: 'var(--bg-2)',
              }}
            ></Icon>
          </div>
        }
        maskStyle={{
          background: '#050505',
          opacity: 0.6,
        }}
        centered
      >
        <div className={classNames(`${prefixCls}-preview-container`)}>
          <div
            style={{
              transform: `translate(${margin[0]}px, ${margin[1]}px)`,
              display: 'flex',
              alignItems: 'center',
              justifyContent: 'center',
              width: '100%',
              height: '100%',
            }}
          >
            <Image
              src={images[_previewIndex]}
              style={{
                maxHeight: '100%',
                maxWidth: '100%',
                transform: `scale(${_scale}) rotate(${_degree}deg)`,
                width: 'auto',
              }}
              preview={false}
              onMouseDown={() => {
                setIsMoving(true);
              }}
              onMouseUp={() => {
                setIsMoving(false);
                setPosition([0, 0]);
              }}
              onMouseMove={e => {
                isMoving && run([e.clientX, e.clientY]);
              }}
              draggable={false}
            ></Image>
          </div>
          <div className={classNames(`${prefixCls}-handle`)}>
            <Icon
              iconName="ZoomIn"
              onClick={() => {
                setScale(pre => pre + 1);
              }}
            ></Icon>
            <Icon
              iconName="ZoomOut"
              onClick={() => {
                setScale(pre => pre - 1 || 1);
              }}
            ></Icon>
            <Icon
              iconName="ImgLeft"
              onClick={() => {
                setDegree(pre => pre - 90);
              }}
            ></Icon>
            <Icon
              iconName="ImgRight"
              onClick={() => {
                setDegree(pre => pre + 90);
              }}
            ></Icon>
          </div>
          <div
            className={classNames(`${prefixCls}-left`, `${prefixCls}-icon`)}
            onClick={() => {
              setMargin([0, 0]);
              setScale(1);
              setDegree(0);
              switchPicture(-1);
            }}
          >
            <Icon iconName="LeftBig"></Icon>
          </div>
          <div
            className={classNames(`${prefixCls}-right`, `${prefixCls}-icon`)}
            onClick={() => {
              setMargin([0, 0]);
              setScale(1);
              setDegree(0);
              switchPicture(1);
            }}
          >
            <Icon iconName="RightBig"></Icon>
          </div>
        </div>
      </Modal>
    </>
  );
};

Image.PreviewGroup = PreviewGroup;

export { Image };
