import React from 'react';
import G6 from '@antv/g6';

let graph = null;
const globalFontSize = 20;
const maxTextWidth = 160;

const COLLAPSE_ICON = function COLLAPSE_ICON(x, y, r) {
  return [
    ['M', x - r, y - r],
    ['a', r, r, 0, 1, 0, r * 2, 0],
    ['a', r, r, 0, 1, 0, -r * 2, 0],
    ['M', x + 2 - r, y - r],
    ['L', x + r - 2, y - r],
  ];
};
const EXPAND_ICON = function EXPAND_ICON(x, y, r) {
  return [
    ['M', x - r, y - r],
    ['a', r, r, 0, 1, 0, r * 2, 0],
    ['a', r, r, 0, 1, 0, -r * 2, 0],
    ['M', x + 2 - r, y - r],
    ['L', x + r - 2, y - r],
    ['M', x, y - 2 * r + 2],
    ['L', x, y - 2],
  ];
};

class Tree extends React.Component {

  componentDidUpdate(prevProps, prevState){
    const { childData, parentNodeId, data } = this.props;

    if (parentNodeId && parentNodeId!== prevProps.parentNodeId) {
      const parentData = this.graph?.findDataById(parentNodeId);
      if (!parentData.children) {
        parentData.children = [];
      }

      parentData.children = parentData.children.filter(item => item.dbType!=='More');
      parentData.children = [...parentData.children, ...childData];
      this.graph?.changeData();

      this.graph?.updateItem(this.graph?.findById(parentNodeId), {
        collapsed: false,
      });

    } else if (data && data !== prevProps.data && parentNodeId===null) {
      this.graph?.destroy();
      this.graph = init(this)(this.elem, this.props.data);
    }
  }

  graph = undefined
  elem = undefined

  render() {
    const { styles } = this.props;
    return (
      <div ref={ref => this.elem = ref} style={styles} />
    );
  }
}

export default Tree;

const init = (ctx) => function (container, data) {
  const width = container.scrollWidth;
  const height = container.scrollHeight;

  const tooltip = new G6.Tooltip({
    offsetX: 10,
    offsetY: 10,
    // the types of items that allow the tooltip show up
    // 允许出现 tooltip 的 item 类型
    itemTypes: ['node'],
    // custom the tooltip's content
    // 自定义 tooltip 内容
    getContent: (e) => {
      const outDiv = document.createElement('div');
      outDiv.style.width = 'fit-content';
      //outDiv.style.padding = '0px 0px 20px 0px';
      outDiv.innerHTML = `
        <h4>${e.item.getModel().text||''}</h4>
        `;
      return outDiv;
    },
  });

  graph = new G6.TreeGraph({
    container,
    animate: false,
    width,
    height,
    maxZoom: 1,
    plugins: [tooltip],
    modes: {
      default: [
        {
          type: 'collapse-expand',
          onChange: function onChange(item, collapsed) {
            const data = item.get('model');
            graph.updateItem(item, {
              collapsed,
            });
            data.collapsed = collapsed;
            return true;
          },
        },
        'drag-canvas',
        'zoom-canvas',
      ],
    },
    defaultNode: {
      type: 'tree-node',
      anchorPoints: [
        [0, 0.5],
        [1, 0.5],
      ],
    },
    defaultEdge: {
      type: 'cubic-horizontal',
      size: 2,
      color: '#e2e2e2',
      style: {
        endArrow: true
      }
    },
    layout: {
      type: 'compactBox',
      direction: 'LR', // H / V / LR / RL / TB / BT
      getId: function getId(d) {
        return d.id;
      },
      getVGap: function getVGap() {
        return 20;
      },
      getHGap: function getHGap() {
        return 200;
      },
    },
  });

  const fittingString = (str, maxWidth, fontSize) => {
    const ellipsis = '...';
    const ellipsisLength = G6.Util.getTextSize(ellipsis, fontSize)[0];
    let currentWidth = 0;
    let res = str;
    const pattern = new RegExp('[\u4E00-\u9FA5]+'); // distinguish the Chinese charactors and letters
    str.split('').forEach((letter, i) => {
      if (currentWidth > maxWidth - ellipsisLength) return;
      if (pattern.test(letter)) {
        // Chinese charactors
        currentWidth += fontSize;
      } else {
        // get the width of single letter according to the fontSize
        currentWidth += G6.Util.getLetterWidth(letter, fontSize);
      }
      if (currentWidth > maxWidth - ellipsisLength) {
        res = `${str.substr(0, i)}${ellipsis}`;
      }
    });
    return res;
  };

  graph.node(function (node) {
    return {
      label: fittingString(node.text||'', maxTextWidth, globalFontSize),
    };
  });

  graph.data(data);
  graph.render();
  graph.fitView();

  graph.on('node:click', function (e) {
    const node = e.item;
    const nodeId = node.get('id');

    const model = node.getModel();

    if (model.dbType==='Dir') {

      const children = model.children;
      if (!children) {
        ctx.props?.loadSubLeafData(model.dirId||'', nodeId);
      }

    } else if (model.dbType === 'Table') {
      
      ctx.props?.onAssetClick(model.tid);
    
    } else if (model.dbType === 'More') {
    
      ctx.props?.loadMoreLeafData(model.pDirId, model.pid, model.index);
    
    }

  });

  if (typeof window !== 'undefined') {
    window.onresize = () => {
      if (!graph || graph.get('destroyed')) return;
      if (!container || !container.scrollWidth || !container.scrollHeight) return;

      graph.changeSize(container.scrollWidth, container.scrollHeight);
    };
  }

  return graph;
}

G6.registerNode(
  'tree-node',
  {
    draw(cfg, group) {    
      const rect = group.addShape('rect', {
        attrs: {
          fill: '#fff',
          // stroke: '#666',
          radius: 2,
          shadowOffsetX: 1,
          shadowOffsetY: 0,
          shadowColor: 'rgba(0, 0, 0, 0.09)',
          shadowBlur: 16,
          cursor: (cfg.dbType==='Dir'||cfg.dbType==='More')?'pointer':'default',
        },
      });

      const topRect = group.addShape('rect', {
        attrs: {
          height: 4,
          fill: '#0069AC',
        }
      })
      
      const content = (cfg.label||'').replace(/(.{19})/g, '$1\n');

      const text = group.addShape('text', {
        attrs: {
          x: 0,
          y: 8,
          fill: '#000',
          fontSize: globalFontSize,
          textAlign: 'left',
          textBaseline: 'middle',
          text: content,
          cursor: (cfg.dbType==='Dir'||cfg.dbType==='More')?'pointer':'default',
        }
      });

      const bbox = text.getBBox();

      if (cfg.dbType==='Dir') {
        if (!cfg.children) {
          group.addShape('marker', {
            attrs: {
              x: bbox.maxX + 12,
              y: bbox.height/2 + 8 -3,
              r: 6,
              symbol: EXPAND_ICON,
              stroke: '#73d13d',
              lineWidth: 2,
              cursor: 'pointer'
            }
          });
        } else if ((cfg.children||[]).length>0) {
          group.addShape('marker', {
            attrs: {
              x: bbox.maxX + 12,
              y: bbox.height/2 + 8 -3,
              r: 6,
              symbol:  cfg.collapsed ? EXPAND_ICON : COLLAPSE_ICON,
              stroke: cfg.collapsed ? '#73d13d' : '#ff4d4f',
              lineWidth: 2,
              cursor: 'pointer',
            }
          });
        }
      }

      topRect.attr({
        x: bbox.minX - 10,
        y: bbox.minY - 10,
        width: bbox.width + (cfg.dbType==='Dir'&&(!cfg.children||((cfg.children||[]).length>0)) ? 38 : 20),
      })

      rect.attr({
        x: bbox.minX - 10,
        y: bbox.minY - 10,
        width: bbox.width + (cfg.dbType==='Dir'&&(!cfg.children||((cfg.children||[]).length>0)) ? 38 : 20),
        height: bbox.height + 20,
      });

      return group;
    },
    update: undefined,
  },
  'single-node'
);   