import React, { FC, useState, useEffect, useMemo, useReducer, useRef, useCallback } from 'react';
import { message } from 'antd';
import Mind from './container/Mind';
import Sidebar from './container/Sidebar';
import Header from './container/Header';
import { IModalProps, IKnowledge } from './types';
import Controller from './container/Controller';
import serviceFactory from './message';
import themeFactory from './theme/themeFactory';
import './theme/index.less';
import { Theme } from './theme/types';
import { expandAll, throttleFn } from './lib/utils';
import { SCALE, SCALE_GAP, SCALE_MAX, SCALE_MIN } from './const';

let clientX = 0;
let clientY = 0;
let isDragStart = false;

const KnowledgeModal: FC<IModalProps> = ({ theme }) => {
  const [currentKnowledge, setCurrentKnowledge] = useState<IKnowledge>({} as IKnowledge);
  const [scale, setScale] = useState(SCALE);
  const initKnowledgeListSnapshotRef = useRef<IKnowledge[]>([]);
  const [knowledgeList, setKnowledgeList] = useState([]);
  const containerRef = useRef(null);
  const service = useMemo(() => serviceFactory.create(), []);
  const themeConfig = useMemo(() => themeFactory.create(theme), []);
  const [deltaX, setDeltaX] = useState(0); // 相对于初始位置的x轴偏移量
  const deltaXRef = useRef(deltaX);
  deltaXRef.current = deltaX;
  const [deltaY, setDeltaY] = useState(0); // 相对于初始位置的y轴偏移量
  const deltaYRef = useRef(deltaY);
  deltaYRef.current = deltaY;

  const onClose = () => {
    service.send({
      type: 'knowledgeMind.closeModal',
      data: {
        body: [],
      },
    });
  };
  const onSave = () => {
    service.send({
      type: 'knowledgeMind.saveImg',
      data: {
        body: {},
      },
    });
  };
  const onExpandAll = useCallback(() => {
    service.send({
      type: 'knowledgeMind.clickExpandAll',
      data: {
        body: {},
      },
    });
    const copyList: IKnowledge[] = JSON.parse(JSON.stringify(initKnowledgeListSnapshotRef.current));
    const knowledge =
      copyList.find((knowledge) => knowledge.id === currentKnowledge.id) || ({} as IKnowledge);
    const knowledgeOfExpandedAll = expandAll(knowledge);
    setCurrentKnowledge(knowledgeOfExpandedAll);
  }, [currentKnowledge]);
  const onReset = useCallback(() => {
    service.send({
      type: 'knowledgeMind.clickReset',
      data: {
        body: {},
      },
    });
    const copyList: IKnowledge[] = JSON.parse(JSON.stringify(initKnowledgeListSnapshotRef.current));
    const knowledge =
      copyList.find((knowledge) => knowledge.id === currentKnowledge.id) || ({} as IKnowledge);
    setCurrentKnowledge(knowledge);
    initUI();
  }, [currentKnowledge]);
  const onFeedback = () => {
    service.send({
      type: 'knowledgeMind.clickFeedback',
      data: {
        body: {},
      },
    });
  };
  const onZoomUp = useCallback(() => {
    service.send({
      type: 'knowledgeMind.clickZoomUp',
      data: {
        body: {},
      },
    });
    if (scale >= SCALE_MAX) {
      return;
    }
    setScale((scale) => scale + SCALE_GAP);
  }, [scale, setScale]);
  const onZoomDown = useCallback(() => {
    service.send({
      type: 'knowledgeMind.clickZoomDown',
      data: {
        body: {},
      },
    });
    if (scale <= SCALE_MIN) {
      return;
    }
    setScale((scale) => scale - SCALE_GAP);
  }, [scale, setScale]);
  const onMouseDown = (e) => {
    isDragStart = true;
    [clientX, clientY] = [e.clientX, e.clientY];
  };
  const onMouseUp = () => {
    isDragStart = false;
    [clientX, clientY] = [0, 0];
  };
  const onMouseMove = (e) => {
    if (!isDragStart) return;
    const [newClientX, newClientY] = [e.clientX, e.clientY];
    const deltaX = newClientX - clientX;
    const deltaY = newClientY - clientY;
    clientX = newClientX;
    clientY = newClientY;
    onMove({
      deltaX,
      deltaY,
    });
  };
  const onMove = useMemo(
    () =>
      throttleFn((e: { deltaX: number; deltaY: number }) => {
        setDeltaX(deltaXRef.current + e.deltaX);
        setDeltaY(deltaYRef.current + e.deltaY);
      }, 10),
    []
  );
  const initUI = () => {
    setDeltaX(0);
    setDeltaY(0);
    setScale(SCALE);
  };
  const onSelectCurrentKnowledge = useCallback(
    (knowledge: IKnowledge) => {
      setCurrentKnowledge(knowledge);
      initUI();
    },
    [setCurrentKnowledge]
  );
  useEffect(() => {
    service.on(
      'knowledgeMind.initKnowledgeList',
      (msg: { body: { knowledgeList: IKnowledge[] } }) => {
        const knowledgeList = msg.body.knowledgeList || [];
        setKnowledgeList(knowledgeList);
        initKnowledgeListSnapshotRef.current = knowledgeList;
      }
    );
    service.on('knowledgeMind.saveImgSuccess', () => {
      message.info('保存成功');
    });
    service.on('knowledgeMind.saveImgError', () => {
      message.info('保存失败');
    });
  }, []);

  useEffect(() => {
    if (knowledgeList?.[0]) {
      setCurrentKnowledge(knowledgeList[0]);
    }
  }, [knowledgeList]);

  // 自适应安卓设备的屏幕
  useEffect(() => {
    if (containerRef.current && themeConfig.type === Theme.Android) {
      const widthParam = /width=(\d*)/.exec(location.search);
      console.assert(widthParam, '没有读取到设备宽度');
      const width = widthParam ? parseInt(widthParam[1], 10) : window.innerWidth;
      containerRef.current.style.transform = `scale(${(width / 1920).toFixed(5)})`;
      containerRef.current.parentNode.style.height = (width / 1920).toFixed(5) * 1164 + 'px';
    }
  }, []);

  return (
    <div className={`${themeConfig.type}-knowledge-mind-modal`} ref={containerRef}>
      <div className="top">
        <Header onCancel={onClose} onOk={onSave} theme={theme} />
      </div>
      <div className="left">
        <Sidebar
          knowledgeList={knowledgeList}
          onSelectCurrentKnowledge={onSelectCurrentKnowledge}
          currentKnowledge={currentKnowledge}
        />
      </div>
      <div className="right">
        <Mind
          scale={scale}
          setScale={setScale}
          width={themeConfig.mindWidth}
          height={themeConfig.mindHeight}
          currentKnowledge={currentKnowledge}
          onMouseDown={onMouseDown}
          onMouseUp={onMouseUp}
          onMove={onMove}
          deltaX={deltaX}
          deltaY={deltaY}
          onMouseMove={onMouseMove}
        />
      </div>
      <div className="right-bottom">
        <Controller
          onExpandAll={onExpandAll}
          onZoomDown={onZoomDown}
          onZoomUp={onZoomUp}
          onFeedback={onFeedback}
          onReset={onReset}
          scale={scale}
          theme={theme}
        />
      </div>
    </div>
  );
};

export default KnowledgeModal;
