import React from 'react';
import { formatLinks, computedNewNodes, computedNewLinks } from './utils';
import createForceFactory from './factory';
import { isEqual, uuid } from '@zenview/micro-utils';
import _ from 'lodash';

class RelationShip extends React.Component {
  constructor(props) {
    super(props);
    const { nodes, links } = props;
    this.domId = `d3-chart-force-${uuid()}`;
    this.config = {
      R: 34,
      nodes,
      links
    };
    this.state = {
      nodes: _.cloneDeep(nodes) || [],
      links: formatLinks(_.cloneDeep(links) || []),
      rawNodes: _.cloneDeep(nodes),
      rawLinks: _.cloneDeep(links),
      isRawDataChange: false
    };
  }
  static getDerivedStateFromProps(props, state) {
    const options = {};
    if (props.nodes && !isEqual(props.nodes, state.rawNodes)) {
      options.isRawDataChange = true;
      options.rawNodes = _.cloneDeep(props.nodes);
    }
    if (props.links && !isEqual(props.links, state.rawLinks)) {
      options.isRawDataChange = true;
      options.rawLinks = _.cloneDeep(props.links);
    }
    return options;
  }
  componentDidMount() {
    this.initForceLayer();
    window.addEventListener('resize', this.initForceLayerDebounced, false);
  }

  initForceLayerDebounced = () => {
    this.debounced && this.debounced.cancel();
    this.debounced = _.debounce(this.initForceLayer, 500);
    this.debounced();
  };
  initForceLayer = () => {
    const { onLineClick, onNodeClick, onRelation, onRemove, onZoom, hasIconAction = true } = this.props;
    const { nodes, links } = this.state;
    const { width, height } = document.getElementById(this.domId).getBoundingClientRect();
    if (this.forceFactory) {
      this.forceFactory.destory();
    }
    const options = {
      width,
      height,
      nodes,
      links,
      onLineClick,
      onNodeClick,
      onRelation,
      onRemove,
      onZoom,
      hasIconAction
    };
    this.forceFactory = createForceFactory(this.domId, options);
  };
  componentDidUpdate() {
    if (this.state.isRawDataChange) {
      this.setState({ isRawDataChange: false });
      this.computedDataChange();
    }
  }
  computedDataChange() {
    const { nodes, links, rawLinks, rawNodes } = this.state;
    const newNodes = computedNewNodes(nodes, rawNodes);
    const newLinks = formatLinks(computedNewLinks(links, rawLinks));
    this.setState({ nodes: newNodes, links: newLinks });
    this.forceFactory.update(newNodes, links);
    clearTimeout(this.timer);
    this.timer = setTimeout(() => {
      this.forceFactory.update(newNodes, newLinks);
    }, 100);
  }

  componentWillUnmount() {
    clearTimeout(this.timer);
    this.debounced && this.debounced.cancel();
    this.forceFactory && this.forceFactory.destory();
    this.forceFactory = null;
    window.removeEventListener('resize', this.initForceLayerDebounced, false);
  }

  render() {
    return <div id={this.domId} style={{ width: '100%', height: '100%' }} />;
  }
}

export default RelationShip;
