import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { deepEqual, pwdPolicy } from 'amos-tool';
import go from 'amos-gojs';
import classnames from 'classnames';
import { nodeDetailTopoAction } from './../../../services/dynamicRingService';

const goObj = go.GraphObject.make;
const deviceSource = '/src/assets/bizView/virtualCloudPlatform';

class TopologyComponent extends Component {

  constructor(props) {
    super(props);
    this.state = {
      detailData: []
    };
    this.diagram = null; //gojs图
    this.customEditor = null;
    this.updateTopologyData = {};
  }

  componentDidMount() {
    this.renderCanvas();
  }


  componentDidUpdate(prevProps, prevState) {
    const { topologyData } = this.props;
    const { nodeData, linkData } = topologyData;
    if (!deepEqual(prevProps.topologyData,this.props.topologyData)) {
      this.diagram.model =  goObj(go.GraphLinksModel,
        {
          linkFromPortIdProperty: 'fromPort',  // required information:
          linkToPortIdProperty: 'toPort',      // identifies data property names
          nodeDataArray: nodeData || [],
          linkDataArray: linkData || []
        });
    }
  }

  // this function is the Node.dragComputation, to limit the movement of the parts
  stayInFixedArea = (part, pt, gridpt) => {
    let diagram = part.diagram;
    if (diagram === null) {return pt;}
		// compute the document area without padding
    let v = diagram.documentBounds.copy();
    v.subtractMargin(diagram.padding);
		// get the bounds of the part being dragged
    let b = part.actualBounds;
    let loc = part.location;
		// now limit the location appropriately
    let x = Math.max(v.x, Math.min(pt.x, v.right - b.width)) + (loc.x - b.x);
    let y = Math.max(v.y, Math.min(pt.y, v.bottom - b.height)) + (loc.y - b.y);
    return new go.Point(x, y);
  }

  // 选择节点
  nodeSelectionChanged = (node) => {
    this.props.nodeSelectionChanged(node);
  }

  // 设备资源图片
  getDeviceSource = (v) => {
    return `${deviceSource}/${v}.png`;
  }

  // 告警图片
  getWarnPic = (v) => {
    if (v) {
      return '/src/assets/bizView/netTopology/alarm.png';
    }
  }

  // 告警高亮
  warnHighlights = (d,v) => {

    let str = [];
    str = d.text.split("#");
    if (d.warnState) {
      this.showWarnHighlights(d, v);
      return d.text.split("#")[0];
    }

    return d.text.split("#")[0];

  }

    // 获取ip
   getIp = (d,v) => {
      let str = [];
      str = d.text.split("#");
      if(str && str.length > 1){
        return d.text.split("#")[1];
      }else{
        return "";
      }

    }

    getIp2 = (d,v) => {
      let str = [];
      str = d.text.split("#");
      if(str && str.length > 2){
        return d.text.split("#")[2];
      }else{
        return "";
      }

    }

  // 获取线颜色
  getLinkColor = (v) => {
    if (v) {
      return '#FF0000';
    }
    return '#00FFFF';
  }

  showWarnHighlights = (d, v) => {
    const oldDom = this[d.key];
    this.isDrag = true;
    if (oldDom) {
      let pos = this.diagram.transformDocToView(go.Point.parse(d.loc));
      oldDom.style.width = '100px';
      oldDom.style.height = '100px';
      oldDom.style.left = `${pos.x + 18}px`;
      oldDom.style.top  = `${pos.y + 20}px`;
    } else {
      let pos = this.diagram.transformDocToView(go.Point.parse(d.loc));
      let customBox = document.createElement('div');
      customBox.style.left = `${pos.x + 10}px`;
      customBox.style.top  = `${pos.y + 26}px`;
      customBox.style.position = 'absolute';
      customBox.style.zIndex = 1;
      customBox.style.width = '100px';
      customBox.style.height = '100px';
      customBox.style.backgroundPosition = 'center';
      customBox.id = d.key;
      customBox.setAttribute('class','amos-help-tip-pulse-second');
      this.diagram.div.appendChild(customBox);
    }
  };

  // 更新位置信息
  updateTopo = () => {
    const { nodeDataArray } = this.updateTopologyData;
    let pos;
    nodeDataArray.filter(item => item.warnState).map(item => {
      pos = this.diagram.transformDocToView(go.Point.parse(item.loc));
      this[item.key].style.left = `${pos.x + 18}px`;
      this[item.key].style.top  = `${pos.y + 20}px`;
    });
  }

  getNodeDetail = (id) => {
    nodeDetailTopoAction(id).then(data => {
      this.setState({
        detailData: data
      });
    });
  }

  renderDetail = () => {
    const { detailData } = this.state;
    return (<div id="toolTipDIV" className="tooltip-content" style={{ position: 'absolute', zIndex: 1000, display: 'none' }}>
      {detailData.map(item => {
        return (<div key={item.name} className="tooltip-item">
          <div className="item-name">{item.name}: </div>
          <div className="item-value">{item.value}</div>
        </div>);
      })}
    </div>);
  }

  // 提示框
  showToolTip = (obj, diagram, tool) => {
    let toolTipDIV = document.getElementById('toolTipDIV');
    let pt = diagram.lastInput.viewPoint;
    toolTipDIV.style.left = `${pt.x + 12}px`;
    toolTipDIV.style.top = `${pt.y}px`;
    toolTipDIV.style.display = 'block';
    this.getNodeDetail(obj.data.id);
  }

  hideToolTip = (diagram, tool) => {
    let toolTipDIV = document.getElementById('toolTipDIV');
    toolTipDIV.style.display = 'none';
  }

  renderCanvas = () => {
    const { topologyData } = this.props;
    const { nodeData, linkData } = topologyData;
    const myToolTip = goObj(go.HTMLInfo, {
      show: this.showToolTip,
      hide: this.hideToolTip
    });
    this.customEditor = goObj(go.HTMLInfo,{
      show: this.showWarnHighlights
    });
    this.diagram = goObj(go.Diagram, this.refs.goJsDiv, {
      // allowHorizontalScroll: false,  // disallow scrolling or panning
      // allowVerticalScroll: false,
      allowZoom: false,              // disallow zooming
      initialContentAlignment: go.Spot.TopLeft,
      initialPosition: new go.Point(0, 0),
      'undoManager.isEnabled': true, //// enable undo & redo 是否可撤回
      'animationManager.isEnabled': false, // 过渡动画
      'textEditingTool.defaultTextEditor': this.customEditor,
      // fixedBounds: new go.Rect(0, 0, this.refs.goJsDiv.clientWidth, this.refs.goJsDiv.clientHeight),
      ModelChanged: (e) => {     // just for demonstration purposes,
        if (e.isTransactionFinished) {  // show the model data in the page's TextArea
          // console.log(e.model.toJson(), 'model');
          this.updateTopologyData = JSON.parse(e.model.toJson());
          this.props.nodeChange(e);
        }
      },
      SelectionMoved: (e) => {
        setTimeout(()=> {
          this.updateTopo();
        },0);
      },
      ViewportBoundsChanged: () => {
        setTimeout(()=> {
          this.updateTopo();
        },0);
      }
    });


    this.diagram.nodeTemplateMap.add('Circle',
      goObj(go.Node, 'Vertical',
        {
          selectionObjectName: 'ICON',
          locationObjectName: 'ICON'
        },
        new go.Binding('position', 'loc', go.Point.parse).makeTwoWay(go.Point.stringify),
        goObj(go.Panel, 'Auto',
          goObj(go.Shape, 'Circle', { name: 'ICON',portId: '',
            width: 22, height: 22, strokeWidth: 0,fill: '#009dd9' },
            ),
        ),
      goObj(go.TextBlock,
        { margin: 15,cursor: 'pointer',font: '15px sans-serif' },
        new go.Binding('text', 'text' )),
        {
          selectionAdornmentTemplate:
              goObj(go.Adornment, 'Auto',
                goObj(go.Shape, 'Circle',
                { fill: null, stroke: '#fbfb7b', strokeWidth: 3 }),
                goObj(go.Placeholder)
              )  // end Adornment
        },
    ));

    this.diagram.nodeTemplateMap.add('Picture',
      goObj(go.Node, 'Vertical',
        {
          locationSpot: go.Spot.Center,
          locationObjectName: 'ICON',
          selectionObjectName: 'ICON',
          // dragComputation: this.stayInFixedArea
          selectionChanged: this.nodeSelectionChanged,
          toolTip: myToolTip
        },
        new go.Binding('position', 'loc', go.Point.parse).makeTwoWay(go.Point.stringify),
        goObj(go.Panel,'Spot',
          goObj(go.Shape, 'Rectangle',
          { fill: 'lightgreen', stroke: null, width: 1, height: 1 }),
          goObj(go.Picture,
            {
              width: 65,
              height: 45,
              alignment: new go.Spot(1, 0, 100 ,0 )
            },
            new go.Binding('source','warnState',(v) => this.getWarnPic(v))
          ),

          goObj(go.TextBlock,
            {
              alignment: new go.Spot(1, 0, 100 ,-1),
              stroke: 'white',
              font: '15px sans-serif'
            },
            new go.Binding('text', 'warnMessage')
          )
        ),
        goObj(go.Picture,
          {
            margin: 0,
            name: 'ICON',
            width: 55,
            height: 55,
            cursor: 'pointer',
            portId: ''
          },
          new go.Binding('source','source',(v) => this.getDeviceSource(v))
        ),
        //图标下面的字
        goObj(go.TextBlock, '无',
          { margin: 3, stroke: 'rgba(63,63,63,1)', font: '14px sans-serif' },
          new go.Binding('text','', (v,d) => this.warnHighlights(v,d)),
          ),

          //ip1
        goObj(go.TextBlock, '无',
        { margin: 3, stroke: '#3399FF', font: '12px sans-serif' },
        new go.Binding('text','', (v,d) => this.getIp(v,d)),
        ),
         //ip2
        goObj(go.TextBlock, '无',
        { margin: 3, stroke: '#3399FF', font: '12px sans-serif' },
        new go.Binding('text','', (v,d) => this.getIp2(v,d)),
        ),
        {
          selectionAdornmentTemplate:
              goObj(go.Adornment, 'Auto',
                goObj(go.Shape,
                { fill: null, stroke: '#fbfb7b', strokeWidth: 3 }),
                goObj(go.Placeholder)
              )  // end Adornment
        }
      )
    );

    this.diagram.nodeTemplateMap.add('Physical',
    goObj(go.Node, 'Vertical',
      {
        locationSpot: go.Spot.Center,
        locationObjectName: 'ICON',
        selectionObjectName: 'ICON',
        // dragComputation: this.stayInFixedArea
        selectionChanged: this.nodeSelectionChanged,
        toolTip: myToolTip
      },
      new go.Binding('position', 'loc', go.Point.parse).makeTwoWay(go.Point.stringify),
      // goObj(go.Panel,'Spot',
      //   goObj(go.Shape, 'Rectangle',
      //   { fill: 'lightgreen', stroke: null, width: 1, height: 1 }),
      //   goObj(go.Picture,
      //     {
      //       width: 65,
      //       height: 45,
      //       alignment: new go.Spot(1, 0, 100 ,0 )
      //     },
      //     new go.Binding('source','warnState',(v) => this.getWarnPic(v))
      //   ),
      //   goObj(go.TextBlock,
      //     {
      //       alignment: new go.Spot(1, 0, 100 ,-1),
      //       stroke: 'white',
      //       font: '15px sans-serif'
      //     },
      //     new go.Binding('text', 'warnMessage')
      //   ),
      // ),
      goObj(go.Panel, 'Spot',
        { fromSpot: go.Spot.RightSide,  // coming out from right side
          toSpot: go.Spot.LeftSide },   // going into at left side
        goObj(go.Shape, 'Rectangle',
        { fill: 'lightgreen', stroke: null, width: 1, height: 1 }),
        goObj(go.Picture,
          {
            margin: 0,
            name: 'ICON',
            width: 150,
            height: 150,
            cursor: 'pointer'
          },
          new go.Binding('source','source',(v) => this.getDeviceSource(v))
        ),
            //绑定点开始
            goObj(go.Shape,
              {
                fromSpot: new go.Spot(0, 0.5, -2, 0),
                toSpot: new go.Spot(0, 0.5, -2, 0)
              },
            { width: 6, height: 6, portId: '', fill: null,stroke: null,toArrow: "standard",alignment: new go.Spot(1, 1, -53, -5) },
              new go.Binding('portId', 'left_1')
            ),
            goObj(go.Shape,
              {
                fromSpot: new go.Spot(0, 0.5, -2, 0),
                toSpot: new go.Spot(0, 0.5, -2, 0)
              },
              { width: 6, height: 6, portId: '', fill: null,stroke: null,alignment: new go.Spot(1, 1, -59, 22) },
                new go.Binding('portId', 'left_2')
              ),
              goObj(go.Shape,
                {
                  fromSpot: new go.Spot(0, 0.5, -2, 0),
                  toSpot: new go.Spot(0, 0.5, -2, 0)
                },
                { width: 6, height: 6, portId: '', fill: null ,stroke: null,alignment: new go.Spot(1, 1, -43, 42) },
                  new go.Binding('portId', 'left_3')
                ),
                goObj(go.Shape,
                  {

                    fromSpot: new go.Spot(0, 5, 2, -22),
                    toSpot: new go.Spot(0, 5, 2, -22)
                  },
                  { width: 6, height: 6, portId: '',fill: null,stroke: null,alignment: new go.Spot(1, 1, -25, 49) },
                    new go.Binding('portId', 'left_4')
                ),

                goObj(go.Shape,
                  {
                    fromSpot: new go.Spot(0, 5, 2, -22),
                    toSpot: new go.Spot(0, 5, 2, -22)
                  },
                  { width: 6, height: 6, portId: '', fill: null,stroke: null,alignment: new go.Spot(1, 1, -2, 49) },
                    new go.Binding('portId', 'left_5')
                  ),
                  goObj(go.Shape,
                    {
                      fromSpot: new go.Spot(0, 5, 2, -22),
                    toSpot: new go.Spot(0, 5, 2, -22)
                    },
                    { width: 6, height: 6, portId: '', fill:null,stroke: null,alignment: new go.Spot(1, 1, 18, 49) },
                      new go.Binding('portId', 'left_6')
                    ),
                 goObj(go.Shape,
                   {
                    fromSpot: new go.Spot(1, 0.5, 2, 0),
                    toSpot: new go.Spot(1, 0.5, 2, 0)
                   },
                   { width: 6, height: 6, portId: '', fill: null,stroke: null,alignment: new go.Spot(1, 1, 46, 50) },
                     new go.Binding('portId', 'right_1')
                   ),
                  goObj(go.Shape,
                    {
                      fromSpot: new go.Spot(1, 0.5, 2, 0),
                      toSpot: new go.Spot(1, 0.5, 2, 0)
                    },
                    { width: 6, height: 6, portId: '', fill: null,stroke: null,alignment: new go.Spot(1, 1, 60, 25) },
                      new go.Binding('portId', 'right_2')
                    ),
              goObj(go.Shape,
                {
                  fromSpot: new go.Spot(1, 0.5, 2, 0),
                  toSpot: new go.Spot(1, 0.5, 2, 0)
                },
                { width: 6, height: 6, portId: '', fill: null,toArrow: "BackwardTriangle",stroke: null,alignment: new go.Spot(1, 1, 63, 5) },
                  new go.Binding('portId', 'right_3')
                ),
                goObj(go.Shape,
                  {
                    fromSpot: new go.Spot(1, 0.5, 2, 0),
                      toSpot: new go.Spot(1, 0.5, 2, 0)
                  },
                  { width: 6, height: 6, portId: '', fill: null,toArrow: "standard",stroke: null,alignment: new go.Spot(1, 1, 45, -15) },
                    new go.Binding('portId', 'right_4')
                  ),
                  goObj(go.Shape,
                    {
                      fromSpot: new go.Spot(1, 0.5, 2, 0),
                      toSpot: new go.Spot(1, 0.5, 2, 0)
                    },
                    { width: 6, height: 6, portId: '', fill: null,toArrow: "standard",stroke: null,alignment: new go.Spot(1, 1, 30, -40) },
                      new go.Binding('portId', 'right_5')
                    ),
                    goObj(go.Shape,
                {
                  fromSpot: new go.Spot(1, 0.5, 2, 0),
                  toSpot: new go.Spot(1, 0.5, 2, 0)
                },
                { width: 6, height: 6, portId: '', fill: null,stroke: null,alignment: new go.Spot(1, 1, 15, -53) },
                  new go.Binding('portId', 'right_6')
                ),
                goObj(go.Shape,
                  {
                    fromSpot: new go.Spot(0, 0.5, -2, 0),
                    fromSpot: new go.Spot(0, 0.5, -2, 0),
                  },
                  { width: 6, height: 6, portId: '', fill: null,stroke: null,alignment: new go.Spot(1, 1, -1, -60) },
                    new go.Binding('portId', 'right_7')
                  ),
                  goObj(go.Shape,
                    {
                      fromSpot: new go.Spot(0, 0.5, -2, 0),
                      fromSpot: new go.Spot(0, 0.5, -2, 0),
                    },
                    { width: 6, height: 6, portId: '', fill: null,stroke: null,alignment: new go.Spot(1, 1, -35, -30) },
                      new go.Binding('portId', 'right_8')
                    ),
              //绑定点结束
      ),
      goObj(go.TextBlock, '无',
        { margin: 3, stroke: 'rgba(63,63,63,1)', font: '14px sans-serif' },
        new go.Binding('text','', (v,d) => this.warnHighlights(v,d)),
        ),
      {
        selectionAdornmentTemplate:
            goObj(go.Adornment, 'Auto',
              goObj(go.Shape,
              { fill: null, stroke: '#fbfb7b', strokeWidth: 3 }),
              goObj(go.Placeholder)
            )  // end Adornment
      }

    )
  );

    this.diagram.groupTemplate = goObj(go.Group, 'Vertical',
      {
        resizable: true,
        locationObjectName: 'SHAPE',
        resizeObjectName: 'SHAPE',
        selectionObjectName: 'SHAPE'
        // dragComputation: this.stayInFixedArea,
        // selectionChanged: this.nodeSelectionChanged
      },
      new go.Binding('position', 'loc', go.Point.parse).makeTwoWay(go.Point.stringify),
      goObj(
        go.Panel,
        'Auto',
        { stretch: go.GraphObject.Horizontal },
        // 定义画板的样式
        goObj(go.Shape, 'Rectangle', {
          fill: '#E5E5E5',
          stroke: '#49ADDA', // node边框
          strokeWidth: 1
        }),

        goObj(
          go.TextBlock, // group title
          {
            height: 24,
            font: 'Bold 14px Sans-Serif',
            textAlign: 'left',
            margin: new go.Margin(0, 0, 0, 12),
            verticalAlignment: go.Spot.Center,
            alignment: go.Spot.TopLeft
          },
          new go.Binding('text','', (v,d) => this.warnHighlights(v,d)),
        )
      ),
      goObj(go.Shape, 'Rectangle',
        {
          name: 'SHAPE',
          parameter1: 14,
          fill: 'rgba(255,255,255,0.2)',
          stroke: 'rgba(28,154,210,1)',
          strokeWidth: 1
        },

        new go.Binding('desiredSize', 'size', go.Size.parse).makeTwoWay(go.Size.stringify),
      )

    );

    this.diagram.linkTemplate =
      goObj(go.Link,
        {
          selectionAdorned: true,

          routing: go.Link.AvoidsNodes,

          corner: 2,
          curve: go.Link.JumpOver,
          fromEndSegmentLength: 60, //设置箭头后线长度
          toEndSegmentLength: 60, //设置箭头后线长度

        },

        goObj(go.Shape, { strokeWidth: 2 },

        new go.Binding('stroke', 'warnState', (v) => this.getLinkColor(v))
        )
      );
      this.diagram.model =  goObj(go.GraphLinksModel,
        {
          linkFromPortIdProperty: 'fromPort',  // required information:
          linkToPortIdProperty: 'toPort',      // identifies data property names
          nodeDataArray: nodeData || [],
          linkDataArray: linkData || []
        });
  }

  render() {
    const { className,style, topologyData } = this.props;
    const { nodeData = [] } = topologyData || {};
    return (
      <div ref="goJsDiv" style={style} className={classnames('topology-net', className)}>
        {
          nodeData.filter(e => e.warnState).map(e => <div className="amos-help-tip-pulse-second warn-node" ref={node => this[e.key] = node} key={e.key} id={e.key} />)
        }
        {nodeData.length > 0 && this.renderDetail()}
      </div>
    );
  }
}

TopologyComponent.propTypes = {
  className: PropTypes.string,
  style: PropTypes.object,
  topologyData: PropTypes.object,
  nodeChange: PropTypes.func,
  nodeSelectionChanged: PropTypes.func
};

TopologyComponent.defaultProps = {
  style: { height: '100%' },
  topologyData: {
    nodeData: [],
    linkData: []
  }
};

export default TopologyComponent;
