import React, { FC, useEffect, useMemo, useRef, useState, useCallback } from 'react';
import { IKnowledge, JsMindCreator, Option } from '../../types';
import jsMind from '../../lib/jsmind';
import AlloyFinger from 'alloyfinger/react/AlloyFinger.jsx';
import { SCALE, SCALE_SMOOTH_GAP, SCALE_MAX, SCALE_MIN } from '../../const';
import { throttleFn } from '../../lib/utils';

interface IProps {
  width: number;
  height: number;
  scale: number; // 当前导图缩放比例
  setScale: any;
  currentKnowledge: IKnowledge;
  onMove: any;
  onMouseDown: any;
  onMouseMove: any;
  onMouseUp: any;
  deltaX: number;
  deltaY: number;
}

const options = {
  container: 'container',
  editable: false,
  theme: 'sugar',
  mode: 'side',
  view: {
    line_width: 1,
    line_color: '#DFE4E9',
  },
  shortcut: {
    enable: false,
  },
};

/**
 * @description 使用单例保证全局只能存在一个jm对象
 * @returns
 */
function getJMInstance() {
  let jm = null;
  return (options: Option) => {
    if (jm === null) {
      jm = new (jsMind as JsMindCreator)(options);
    }
    return jm;
  };
}

const Mind: FC<IProps> = ({
  width,
  height,
  currentKnowledge,
  scale,
  onMouseDown,
  onMouseUp,
  onMove,
  onMouseMove,
  deltaX,
  deltaY,
  setScale,
}) => {
  const mindRef = useRef();
  const scaleRef = useRef(SCALE);
  scaleRef.current = scale;
  const getJM = useMemo(() => getJMInstance(), []);

  useEffect(() => {
    if (!currentKnowledge || !currentKnowledge.id) {
      return;
    }
    const mind = {
      /* 元数据，定义思维导图的名称、作者、版本等信息 */
      meta: {
        name: '',
        author: '',
        version: '',
      },
      /* 数据格式声明 */
      format: 'node_tree',
      /* 数据内容 */
      data: currentKnowledge,
    };
    const jm = getJM(options);
    jm.show(mind);
  }, [currentKnowledge]);
  const onSmoothSetScale = useCallback((e: React.WheelEvent) => {
    if (e.deltaY > 0) {
      if (scaleRef.current >= SCALE_MAX) {
        return;
      }
      setScale((scale) => scale + SCALE_SMOOTH_GAP);
    } else {
      if (scaleRef.current <= SCALE_MIN) {
        return;
      }
      setScale((scale) => scale - SCALE_SMOOTH_GAP);
    }
  }, []);
  const throttledSmoothSetScale = useMemo(() => throttleFn(onSmoothSetScale, 10), []);
  return (
    <div className="mind-container" onMouseLeave={onMouseUp} onMouseUp={onMouseUp} onWheel={throttledSmoothSetScale}>
      <AlloyFinger onPressMove={onMove}>
        <div
          onMouseDown={onMouseDown}
          onMouseMove={onMouseMove}
          style={{
            width: width,
            height: height,
            transform: `scale(${scale / SCALE}) translate(${deltaX}px, ${deltaY}px)`,
          }}
          id="container"
          ref={mindRef}
          className="mind"
          draggable={false}
        />
      </AlloyFinger>
    </div>
  );
};

export default Mind;
