/**
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/* eslint-disable */
import * as d3 from 'd3';
import d3tip from 'd3-tip';
export default class TraceMap {
  constructor(el,row, showSpanModal,smax,smin,cmax,cmin) {
    this.type = {
      MQ: '#bf99f8',
      Http: '#72a5fd',
      Database: '#ff6732',
      Unknown: '#ffc107',
      Cache: '#00bcd4',
      RPCFramework: '#ee4395',
    };
    this.smax = smax;
    this.smin = smin;
    this.cmax = cmax;
    this.cmin = cmin;
    this.showSpanModal = showSpanModal;
    this.el = el;
    this.i = 0;
    this.j = 0;
    this.width = el.clientWidth;
    this.height = (row.length - 1) * 80;
    this.body = d3
      .select(this.el)
      .style('height', this.height + 'px')
      .append('svg')
      .attr('width', this.width)
      .attr('height', this.height);
    this.tip = d3tip()
      .attr('class', 'd3-tip')
      .offset([10, 0])
      .html(d => d.data.label);
    this.timeTip = d3tip()
      .attr('class', 'd3-tip')
      .offset([-8, 0])
      .html(d => d.data.label);
    this.body.call(this.timeTip);
    this.body.call(this.tip);
    this.treemap = d3.tree().size([this.height * 0.8, this.width]);
  }
  init(data, row) {
    this.row = row;
    this.data = data;
    this.min = d3.min(this.row.map(i => i.startTime));
    this.max = d3.max(this.row.map(i => i.endTime - this.min));
    this.list = Array.from(new Set(this.row.map(i => i.serviceCode)));
    this.sequentialScale = d3
      .scaleSequential()
      .domain([0, this.list.length])
      .interpolator(d3.interpolateCool);
    this.svg = this.body.append('g').attr('transform', d => `translate(0, ${this.row.length * 14})`).append('g');
    this.timeGroup = this.body.append('g').attr('class','timeGroup').attr('transform', d => 'translate(5,30)');
    this.body.call(this.getZoomBehavior(this.svg));
    this.root = d3.hierarchy(this.data, d => d.children);
    this.root.x0 = this.height / 2;
    this.root.y0 = 0;
  }
  resize() {
    this.body
    .select('.xAxis')
    .remove();
    this.body
      .select('.timeGroup')
      .remove();
    this.width = this.el.clientWidth;
    this.body.attr('width', this.width);
    this.xScale = d3
    .scaleLinear()
    .domain([0, this.max])
    .range([0, this.width - 10]);
    this.xAxis = d3.axisTop(this.xScale).tickFormat(d => {
      if (d === 0) return 0;
      if (d >= 1000) return d / 1000 + 's';
      return d + ' ms';
    });
    this.body
    .append('g')
    .attr('class', 'xAxis')
    .attr('transform', `translate(5,20)`)
    .call(this.xAxis);
    this.timeGroup = this.body.append('g').attr('class','timeGroup').attr('transform', d => 'translate(5,30)');
    this.updatexAxis(this.root);
  }
  draw() {
    this.xScale = d3
      .scaleLinear()
      .domain([0, this.max])
      .range([0, this.width - 10]);
      
    this.xAxis = d3.axisTop(this.xScale).tickFormat(d => {
      if (d === 0) return 0;
      if (d >= 1000) return d / 1000 + 's';
      return d + ' ms';
    });
    this.body
    .append('g')
    .attr('class', 'xAxis')
    .attr('transform', `translate(5,20)`)
    .call(this.xAxis);
    this.updatexAxis(this.root);
    this.update(this.root);
  }
  update(source) {
    const that = this;
    const links = this.nodes.slice(1);
    const node = this.svg.selectAll('g.node').data(this.nodes, d => {
      return d.id|| (d.id = ++this.i);
    });
    // node
    const nodeEnter = node
      .enter()
      .append('g')
      .attr('class', 'node')
      .attr('transform', `translate(${source.y0},${source.x0})`)
      .on('mouseover', function(d, i) {
        that.tip.show(d, this);
        const _node = that.timeUpdate._groups[0].filter(group => group.__data__.id === (i+1));
        if(_node.length){
          that.timeTip.show(d, _node[0].children[1]);
        }
      })
      .on('mouseout', function(d, i) {
        that.tip.hide(d, this);
        const _node = that.timeUpdate._groups[0].filter(group => group.__data__.id === (i+1));
        if(_node.length){
          that.timeTip.hide(d, _node[0].children[1]);
        }
      })
      .on('click', (d, i) => {
        this.showSpanModal(
          d.data,
          { width: '100%', top: -10, left: '0' },
          d3.select(nodeEnter._groups[0][i]).append('rect')
        );
        d3.event.stopPropagation();
      });
    const nodeSelfDur = nodeEnter
      .append('g')
      .style('opacity', 0)
      .attr('class','trace-tree-node-selfdur')
      .attr('transform', 'translate(0,-39)')
    nodeSelfDur
      .append('rect')
      .attr('width', 65)
      .attr('height', 16)
      .attr('rx', 3)
      .attr('ry', 3)
      .attr('fill', '#333')
    nodeSelfDur
      .append('text')
      .attr('dx', 5)
      .attr('dy', 11)
      .text(d=> {
        return d.data.dur + ' ms'
      })
      .attr('fill', '#fff');
    const nodeSelfChild = nodeEnter
      .append('g')
      .style('opacity', 0)
      .attr('class','trace-tree-node-selfchild')
      .attr('transform', 'translate(0,-39)')
      nodeSelfChild
      .append('rect')
      .attr('width', 110)
      .attr('height', 16)
      .attr('rx', 3)
      .attr('ry', 3)
      .attr('fill', '#333')
      nodeSelfChild
      .append('text')
      .attr('dx', 5)
      .attr('dy', 11)
      .text(d=> `children: ${d.data.childrenLength}`)
      .attr('fill', '#fff') 
    nodeEnter
      .append('rect')
      .attr('class', 'block')
      .attr('x', '0')
      .attr('y', '-20')
      .attr('fill', d => (d.data.isError ? '#ff57221a' : '#f7f7f7'))
      .attr('stroke', d => (d.data.isError ? '#ff5722aa' : '#e4e4e4'));
    nodeEnter
      .append('rect')
      .attr('class', 'content')
      .attr('stroke', d => d.data.isError ? '#ff5722aa' : '#e4e4e4');
    nodeEnter
      .append('rect')
      .attr('class', 'service')
      .attr('x', '-0.5')
      .attr('y', '-20.5')
      .style('fill', d => `${this.sequentialScale(this.list.indexOf(d.data.serviceCode))}`);
    nodeEnter
      .append('text')
      .attr('dy', 13)
      .attr('dx', 10)
      .attr('stroke', '#333')
      .attr('text-anchor', 'start')
      .text(d => d.data.label.length > 19 ? d.data.label.slice(0, 19) : d.data.label);

    nodeEnter
      .append('text')
      .attr('dy', -7)
      .attr('dx', 12)
      .attr('text-anchor', 'start')
      .attr('fill', d => this.type[d.data.layer])
      .attr('stroke', d => this.type[d.data.layer])
      .text(d => d.data.layer);

    nodeEnter
      .append('text')
      .attr('dy', -7)
      .attr('x', 95)
      .attr('stroke', '#333')
      .attr('text-anchor', 'start')
      .text(d => d.data.endTime ? d.data.endTime - d.data.startTime + ' ms' : d.data.traceId);

    nodeEnter
      .append('circle')
      .attr('class', 'node')
      .attr('r', 4)
      .attr('cx', '158')
      .style('fill', d => d._children ? '#8543e0aa' : '#fff')
      .on('click', click);

    this.nodeUpdate = nodeEnter.merge(node);

    this.nodeUpdate
      .transition()
      .duration(600)
      .attr('transform', function(d) {
        return 'translate(' + d.y + ',' + d.x + ')';
      });

    this.nodeUpdate
      .select('circle.node')
      .attr('r', 4)
      .attr('cx', '158')
      .style('fill', d => d._children ? '#8543e0aa' : '#fff')
      .attr('cursor', 'pointer');

    const nodeExit = node
      .exit()
      .transition()
      .duration(600)
      .attr('transform', function(d) {
        return 'translate(' + source.y + ',' + source.x + ')';
      })
      .remove();

    // link
    const link = this.svg.selectAll('path.link').data(links, d => d.id);

    const linkEnter = link
      .enter()
      .insert('path', 'g')
      .attr('class', 'link')
      .attr('d', function(d) {
        const o = { x: source.x0, y: source.y0 };
        return diagonal(o, o);
      });

    const linkUpdate = linkEnter.merge(link);

    linkUpdate
      .transition()
      .duration(600)
      .attr('d', function(d) {
        return diagonal(d, d.parent);
      });

    link
      .exit()
      .transition()
      .duration(600)
      .attr('d', function(d) {
        var o = { x: source.x, y: source.y };
        return diagonal(o, o);
      })
      .remove();

    function diagonal(s, d) {
      return `M ${s.y} ${s.x}
      C ${s.y - 30} ${s.x}, ${d.y + 188} ${d.x},
      ${d.y + 158} ${d.x}`;
    }
    function click(d, i) {
      // that.tip.hide(d, this);
      // that.timeTip.hide(d, that.timeUpdate._groups[0][i]);
      if (d.children) {
        d._children = d.children;
        d.children = null;
      } else {
        d.children = d._children;
        d._children = null;
      }
      that.updatexAxis(d);
      that.update(d);
      d3.event.stopPropagation();
    }
  }
  updatexAxis(source) {
    // time
    const that = this;
    this.nodes = this.treemap(this.root).descendants();
    let index = -1;
    this.nodes.forEach(function(d) {
      d.y = d.depth * 200;
      d.timeX = ++index * 12;
      d.x0 = d.x;
      d.y0 = d.y;
    });
    const timeNode = this.timeGroup.selectAll('g.time').data(this.nodes, d => {
      return d.id|| (d.id = ++this.j);
    });
    this.timeNode = timeNode;
    const timeEnter = timeNode
      .enter()
      .append('g')
      .attr('class', 'time')
      .attr('transform', d => `translate(0,${d.timeX})`)
      .on('mouseover', function(d, i) {
        that.timeTip.show(d, this);
        const _node = that.nodeUpdate._groups[0].filter(group => group.__data__.id === (i+1));
        if(_node.length){
          that.tip.show(d, _node[0]);
        }
      })
      .on('mouseout', function(d, i) {
        that.timeTip.hide(d, this);
        const _node = that.nodeUpdate._groups[0].filter(group => group.__data__.id === (i+1));
        if(_node.length){
          that.tip.hide(d, _node[0]);
        }
      })
      .on('click', (d, i) => {
        this.showSpanModal(
          d.data,
          { width: '100%', top: -10, left: '0' },
          d3.select(that.timeUpdate._groups[0][i]).append('rect')
        );
        d3.event.stopPropagation();
      });
    timeEnter
      .append('rect')
      .attr('height', 10)
      .attr('width', this.width)
      .attr('y', -4)
      .attr('class', 'time-bg');
    timeEnter
      .append('rect')
      .attr('class', 'time-inner')
      .attr('height', 8)
      .attr('width', d => {
        if (!d.data.endTime || !d.data.startTime) return 0;
        return this.xScale(d.data.endTime - d.data.startTime) + 1;
      })
      .attr('rx', 2)
      .attr('ry', 2)
      .attr(
        'x',
        d => (!d.data.endTime || !d.data.startTime ? 0 : this.xScale(d.data.startTime - this.min))
      )
      .attr('y', -3)
      .style('fill', d => `${this.sequentialScale(this.list.indexOf(d.data.serviceCode))}`);
    timeEnter
      .append('rect')
      .style('opacity',0)
      .attr('class', 'time-inner-duration')
      .attr('height', 8)
      .attr('width', d => {
        if (!d.data.dur) return 1;
        return this.xScale(d.data.dur) + 1;
      })
      .attr('rx', 2)
      .attr('ry', 2)
      .attr(
        'x',
        d => (!d.data.endTime || !d.data.startTime ? 0 : this.xScale(d.data.startTime - this.min))
      )
      .attr('y', -3)
      .style('fill', d => `${this.sequentialScale(this.list.indexOf(d.data.serviceCode))}`);

    this.timeUpdate = timeEnter.merge(timeNode);
    this.timeUpdate
      .transition()
      .duration(600)
      .attr('transform', d => `translate(0,${d.timeX})`);

    const timeExit = timeNode
      .exit()
      .transition()
      .duration(600)
      .attr('transform', 'translate(0 ,10)')
      .remove();
  }
  setDefault() {
    d3.selectAll('.time-inner').style('opacity', 1);
    d3.selectAll('.time-inner-duration').style('opacity', 0);
    d3.selectAll('.trace-tree-node-selfdur').style('opacity', 0);
    d3.selectAll('.trace-tree-node-selfchild').style('opacity', 0);
    this.nodeUpdate._groups[0].forEach(i => {
      d3.select(i).style('opacity', 1);
    })
  }
  topChild() {
    d3.selectAll('.time-inner').style('opacity', 1);
    d3.selectAll('.time-inner-duration').style('opacity', 0);
    d3.selectAll('.trace-tree-node-selfdur').style('opacity', 0);
    d3.selectAll('.trace-tree-node-selfchild').style('opacity', 1);
    this.nodeUpdate._groups[0].forEach(i => {
      d3.select(i).style('opacity', .2);
      if(i.__data__.data.childrenLength >= this.cmin && i.__data__.data.childrenLength <= this.cmax){
        d3.select(i).style('opacity', 1);
      }
    })
  }
  topSlow() {
    d3.selectAll('.time-inner').style('opacity', 0);
    d3.selectAll('.time-inner-duration').style('opacity', 1);
    d3.selectAll('.trace-tree-node-selfchild').style('opacity', 0);
    d3.selectAll('.trace-tree-node-selfdur').style('opacity', 1);
    this.nodeUpdate._groups[0].forEach(i => {
      d3.select(i).style('opacity', .2);
      if(i.__data__.data.dur >= this.smin && i.__data__.data.dur <= this.smax){
        d3.select(i).style('opacity', 1);
      }
    })
  }
  getZoomBehavior(g) {
    return d3
      .zoom()
      .scaleExtent([0.3, 10])
      .on('zoom', () => {
        g.attr(
          'transform',
          `translate(${d3.event.transform.x},${d3.event.transform.y})scale(${d3.event.transform.k})`
        );
      });
  }
}
