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

import circle from './circle.93e1.png'
import node from './node-bg-select.171e.png'

const colors = [
  '#BDD2FD',
  '#C2C8D5',
  '#FBE5A2',
  '#F6C3B7',
  '#B6E3F5',
  '#D3C6EA',
  '#FFD8B8',
  '#AAD8D8',
  '#FFD6E7',
];

export 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],
  ];
};
export 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],
  ];
};

const globalFontSize = 12;

let graph = null;

class Relation extends React.Component {

  componentDidMount() {
    const { type, loadMoreData } = this.props;

    const container = document.getElementById(`container${type || ''}`);
    if (!container) return;

    const width = container.scrollWidth || 500;
    const height = container.scrollHeight || 500;

    console.debug(container.scrollWidth)

    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: `container${type || ''}`, animate: false,
      width,
      height,
      plugins: [tooltip],
      // linkCenter: true,
      maxZoom: 1,
      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',
        ],
      },
      layout: {
        type: 'dendrogram',
        direction: 'RL',
        getId: function getId(d) {
          return d.id;
        },
        getVGap: () => {
          return 20;
        },
        getHGap: () => {
          return 40;
        },
        radial: true,
      },
      defaultNode: {
        type: 'relation-node',
        anchorPoints: [
          [0, 0.5],
          [1, 0.5],
        ],
      },
      defaultEdge: {
        // type: 'cubic-horizontal',
        size: 2,
        color: '#e2e2e2',
      },
    });


    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 || '', node.size - 32, globalFontSize),
      };
    });

    this.layoutGraph();

    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 && loadMoreData) {
          loadMoreData(model.dirId || '', nodeId);
        }
      } else if (model.dbType !== 'Root') {
        //通过资产id跳转到资产详情页
        // history && history.push(`${ContextPath}/home`);
      }

    });

    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);
      };
    }

  }

  layoutGraph = () => {
    const { data } = this.props;

    if (graph && data) {

      function recursionTreeData(treeData, depth) {
        if ((treeData || []).length === 0) return;

        (treeData || []).forEach((item, index) => {

          item.size = (100 - depth * 20) > 60 ? (100 - depth * 20) : 60;
          item.depth = depth;
          recursionTreeData(item.children || [], depth + 1);
        })
      }

      data.size = 100;
      data.depth = 0;
      recursionTreeData(data.children || [], 1);

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

    }
  }

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

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

      let depth = childData.depth + 1;
      (childData || []).forEach((item, index) => {

        item.size = (100 - depth * 20) > 60 ? (100 - depth * 20) : 60;
        item.depth = depth;
      })

      parentData.children = childData;
      graph.changeData();

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

    } else if (data !== prevProps.data) {
      this.layoutGraph();
    }
  }

  render() {
    const { type } = this.props;

    return (
      <div id={`container${type || ''}`} style={{ width: '100%', height: '100%', backgroundImage: 'linear-gradient(to bottom left,#2e3b4e,#0d0d13 52%,#0d0d13)' }}></div>
    );
  }
}

export default Relation;


let root = null, radius = false

G6.registerNode(
  'relation-node',
  {
    draw(cfg, group) {

      let [x, y] = [0, 30]

      if (cfg.depth === 0) {
        root = cfg
        radius = cfg?.children?.length > 10
      } else if (cfg?.children?.length > 10) {
        [x, y] = textXY(root, cfg)
      }

      group.addShape('circle', {
        attrs: {
          x: 0,
          y: 0,
          r: (radius && cfg.depth !== 0) ? 10 : cfg.size / 4,
          fill: colors[cfg.depth % colors.length],
        },
      });

      const text = group.addShape('text', {
        attrs: {
          x,
          y,
          fill: '#fff',
          fontSize: globalFontSize,
          textAlign: 'center',
          textBaseline: 'middle',
          text: (cfg.label || ''),
        }
      });

      const bbox = text.getBBox();

      if (cfg.dbType === 'Root' || cfg.dbType === 'Dir') {
        if (!cfg.children) {
          group.addShape('marker', {
            attrs: {
              x: bbox.maxX,
              y: bbox.maxY,
              r: 6,
              symbol: EXPAND_ICON,
              stroke: '#73d13d',
              lineWidth: 2,
            }
          });
        } else if (cfg?.children?.length > 10) {
          group.addShape('marker', {
            attrs: {
              x: bbox.maxX + 8,
              y: bbox.height >> 1,
              r: 6,
              symbol: cfg.collapsed ? EXPAND_ICON : COLLAPSE_ICON,
              stroke: cfg.collapsed ? '#73d13d' : '#ff4d4f',
              lineWidth: 2,
            }
          });
        }
        cfg.anchorPoints = [[0.5, 0.5]]
      } else {
        cfg.anchorPoints = [

          [0, 0.5],//右边
          [0, .7],
          [.1, .8],
          [.2, .8],
          [.3, .8],//顶部
          [0, .3],
          [.1, .2],
          [.2, .2],
          [.3, .2],//底部

          [1, 0.5],//左边
          [1, .7],
          [.9, .8],
          [.8, .8],
          [.7, .8],//顶部
          [1, .3],
          [.9, .2],
          [.8, .2],
          [.7, .2],//底部

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

G6.registerNode(
  'relation-node-foucs',
  {
    draw(cfg, group) {

      const width = 100;
      const height = 100;
      group.addShape('image', {
        attrs: {
          x: -width / 2,
          y: -height / 2,
          width,
          height,
          img: node,
        },
        name: 'image-shape',
      });
      const image = group.addShape('image', {
        attrs: {
          x: -width / 2,
          y: -height / 2,
          width,
          height,
          img: circle,
        },
        name: 'image-shape',
      });
      image.animate(
        (ratio) => {
          const toMatrix = G6.Util.transform(
            [1, 0, 0, 0, 1, 0, 0, 0, 1],
            [['r', ratio * Math.PI * 2]],
          );
          return {
            matrix: toMatrix,
          };
        },
        {
          repeat: true,
          duration: 3000,
          easing: 'easeLinear',
        },
      );

      let [x, y] = [0, 30]

      if (cfg.depth === 0) {
        root = cfg
        radius = cfg?.children?.length > 10
      } else if (cfg?.children?.length > 10) {
        [x, y] = textXY(root, cfg)
      }

      group.addShape('circle', {
        attrs: {
          x: 0,
          y: 0,
          r: (radius && cfg.depth !== 0) ? 10 : cfg.size / 4,
          fill: colors[cfg.depth % colors.length],
        },
      });

      const text = group.addShape('text', {
        attrs: {
          x,
          y,
          fill: '#fff',
          fontSize: globalFontSize,
          textAlign: 'center',
          textBaseline: 'middle',
          text: (cfg.label || ''),
        }
      });

      const bbox = text.getBBox();

      if (cfg.dbType === 'Root' || cfg.dbType === 'Dir') {
        if (!cfg.children) {
          group.addShape('marker', {
            attrs: {
              x: bbox.maxX,
              y: bbox.maxY,
              r: 6,
              symbol: EXPAND_ICON,
              stroke: '#73d13d',
              lineWidth: 2,
            }
          });
        } else if (cfg?.children?.length > 10) {
          group.addShape('marker', {
            attrs: {
              x: bbox.maxX + 8,
              y: bbox.height >> 1,
              r: 6,
              symbol: cfg.collapsed ? EXPAND_ICON : COLLAPSE_ICON,
              stroke: cfg.collapsed ? '#73d13d' : '#ff4d4f',
              lineWidth: 2,
            }
          });
        }
        cfg.anchorPoints = [[0.5, 0.5]]
      } else {
        cfg.anchorPoints = [

          [0, 0.5],//右边
          [0, .7],
          [.1, .8],
          [.2, .8],
          [.3, .8],//顶部
          [0, .3],
          [.1, .2],
          [.2, .2],
          [.3, .2],//底部

          [1, 0.5],//左边
          [1, .7],
          [.9, .8],
          [.8, .8],
          [.7, .8],//顶部
          [1, .3],
          [.9, .2],
          [.8, .2],
          [.7, .2],//底部

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




function textXY(root, cfg) {
  const txtWidth = 10
  const { x, y } = cfg
  const _y = y - root.y, _x = x - root.x
  const rad = 10
  const angle = Math.atan2(_y, _x)
  const sinAngle = Math.sin(angle), cosAngle = Math.cos(angle)
  // console.log(angle, sinAngle, cosAngle)
  const radX = rad
  const radY = rad + Math.abs(sinAngle) * 10 + Math.abs(Math.pow(sinAngle, Math.abs(Math.round(sinAngle * 100)))) * 30 //Math.pow(Math.E, 80 * Math.log(Math.abs(sinAngle))) * 40
  // console.log(angle, rad, txt) 
  return [
    // 右侧文字(中间向右侧15px,上下部向左靠20px) : 左侧
    radX * cosAngle + (cosAngle > 0 ? txtWidth + 15 - Math.abs(sinAngle * 20) : - (txtWidth + 15 - Math.abs(sinAngle * 20))),
    radY * sinAngle
  ];
} 