import React, { useMemo, useState, useEffect, useCallback, useContext } from 'react';
import styles from './index.less';
import { Tree } from '@easyv/antd';
import { connect } from 'react-redux';
import Icon from '../Icon';
import isEqual from 'lodash/isEqual';
import { DownOutlined } from '@ant-design/icons';
import { Layer } from '../../index';
import { Resizable } from 're-resizable';
import { useSizeByDomId } from 'components/easyUse';
import { selectLayers } from 'models/create-app';
import { NodesContext } from '../../Context/index';
import { useLocalStorage } from 'components/easyUse';
import { updateMenuState, updateLayerNodeEages, setCurrentNode } from 'models/node';
import message from 'components/message';

const deepMap = (data: any[] = [], deepKey = 'layers') => {
  return data.reduce((all, item) => {
    const { title, value, children = [], color, cardId } = item;
    const result = {
      title,
      value,
      key: value,
      cardId,
      disabled: !color,
      children: deepMap(children),
      icon: color && <Icon color={color} />
    };
    return (
      // eslint-disable-next-line no-prototype-builtins
      item.hasOwnProperty(deepKey) ? all.concat({ ...result, [deepKey]: deepMap(item[deepKey], deepKey) }) : all.concat(result)
    );
  }, []);
};

function Layers({
  layers,
  id,
  width = 188,
  leftCollapsed,
  currents,
  setCurrentNode
}: {
  setCurrentNode: (id: string) => void;
  currents: string[];
  id: number;
  layers: Layer[];
  width?: number;
  leftCollapsed;
}) {
  const { width: windowWidth = 0, height: windowHeight = 0 } = useSizeByDomId();
  const [state, setState] = useLocalStorage(id);
  const [selectedKeys, setSelectedKeys] = useState<string[]>([]);
  const { setActivatedState, onContextMenu, canvas } = useContext(NodesContext);

  const treeData = useMemo(() => {
    return deepMap(layers);
  }, [layers]);

  useEffect(() => {
    !isEqual(currents, selectedKeys) && setSelectedKeys(currents.map((id) => id.replace(/(.*)Card-/, '')));
  }, [currents]);

  const adaptRuler = useCallback(
    (_e, _direction, ref) => {
      Mousetrap.trigger('command+1');
      const value = parseInt(ref.style.width);
      setState(value);
    },
    [id]
  );

  const onRightClick = ({ event, node }) => {
    if (node.disabled) {
      return;
    }
    onSelect([node.key], { node });
    onContextMenu({ event, id: node.value });
  };

  const onSelect = (selectKeys, { node }) => {
    const nodeId = (node?.cardId || node?.value) + '';
    const _node = canvas?.getNode(nodeId);

    if (nodeId && _node) {
      const { positionAbsolute, width = 0, height = 0 } = _node;
      if (positionAbsolute && width && height) {
        const { x, y } = positionAbsolute;
        const nodeScale = 1.2;
        canvas?.fitBounds(
          {
            x,
            y,
            width,
            height
          },
          {
            padding: nodeScale,
            duration: 300
          }
        );
        setCurrentNode(nodeId); // redux current 选中
        setActivatedState(''); // 清空隐藏不相关状态
      }
    } else {
      message.error('节点不存在');
    }
  };

  if (!id) {
    return null;
  }

  return (
    <Resizable
      size={{ width: state || width, height: windowHeight - 64 }} //不能设置为auto，这样宽高改变的时候scrollTop就会置为0
      enable={{ right: true }}
      minWidth={188}
      maxWidth={windowWidth - 660}
      onResizeStop={adaptRuler}
      style={{ display: leftCollapsed ? 'none' : 'block' }}
      handleClasses={{ right: styles.handle }}
      handleStyles={{ right: { width: 3, right: 0 } }}>
      <div className={styles.layers}>
        <div className={styles.title}>
          <span>图层</span>
        </div>
        <div className={styles.menuBox}>
          <Tree
            onSelect={onSelect}
            multiple={true}
            selectedKeys={selectedKeys}
            showIcon
            blockNode
            switcherIcon={<DownOutlined />}
            onRightClick={onRightClick}
            treeData={treeData}
          />
        </div>
      </div>
    </Resizable>
  );
}
const mapStateToProps = ({ createApp, node }) => {
  const { leftCollapsed } = createApp;

  return {
    leftCollapsed,
    currents: node.currents
  };
};

export default connect(mapStateToProps, {
  updateMenuState,
  setCurrentNode,
  selectLayers,
  updateLayerNodeEages
})(Layers);
