/**</template>
 * 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.
 */

import * as d3 from 'd3';
import d3tip from 'd3-tip';
/* eslint-disable */
const type = {
  MQ: '#bf99f8',
  Http: '#72a5fd',
  Database: '#ff6732',
  Unknown: '#ffc107',
  Cache: '#00bcd4',
  RPCFramework: '#ee4395',
};
export default class Trace {
  constructor(el, show) {
    this.barHeight = 48;
    this.show = show;
    this.el = el;
    this.i = 0;
    this.width = el.clientWidth;
    this.height = el.clientHeight;
    this.svg = d3
      .select(this.el)
      .append('svg')
      .attr('width', this.width)
      .attr('height', this.height);
    this.treemap = d3.tree().size([this.height * 0.7, this.width]);
    this.tip = d3tip()
      .attr('class', 'd3-tip')
      .offset([-8, 0])
      .html(d => `
      <div class="mb-5">${d.data.label}</div>
      ${d.data.dur?'<div class="sm">SelfDuration: ' + d.data.dur + 'ms</div>' : ''}
      ${(d.data.endTime - d.data.startTime)?'<div class="sm">TotalDuration: ' + (d.data.endTime - d.data.startTime) + 'ms</div>' : ''}
      `);
    this.svg.call(this.tip);
  }
  diagonal(d) {
    return `M ${d.source.y} ${d.source.x + 5}
    L ${d.source.y} ${d.target.x - 30}
    L${d.target.y} ${d.target.x - 20}
    L${d.target.y} ${d.target.x - 5}`;
  }
  init(data, row) {
    d3.select('.trace-xaxis').remove();
    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.xScale = d3
      .scaleLinear()
      .range([0, this.width * 0.387])
      .domain([0, this.max]);
    this.xAxis = d3.axisTop(this.xScale).tickFormat(d => {
      if(d === 0) return 0;
      if(d>=1000) return d/1000 + 's';
      return d;
    });
    this.svg.attr('height', (this.row.length+1) * this.barHeight);
    this.svg
    .append('g')
    .attr('class','trace-xaxis')
    .attr('transform', `translate(${this.width * 0.618 -20 },${30})`)
    .call(this.xAxis);
    this.sequentialScale = d3
      .scaleSequential()
      .domain([0, this.list.length + 1])
      .interpolator(d3.interpolateCool);
    this.root = d3.hierarchy(this.data, d => d.children);
    this.root.x0 = 0;
    this.root.y0 = 0;
  }
  draw() {
    this.update(this.root);
  }
  click(d, scope) {
    if (!d.data.type) return;
    if (d.children) {
      d._children = d.children;
      d.children = null;
    } else {
      d.children = d._children;
      d._children = null;
    }
    scope.update(d);
  }
  update(source) {
    const that = this;
    const nodes = this.root.descendants();
    let index = -1;
    this.root.eachBefore(n => {
      n.x = ++index * this.barHeight + 24;
      n.y = n.depth * 12;
    });
    const node = this.svg
      .selectAll('.trace-node')
      .data(nodes, d => d.id || (d.id = ++this.i));
    const nodeEnter = node
      .enter()
      .append('g')
      .attr('transform', `translate(${source.y0},${source.x0})`)
      .attr('class', 'trace-node')
      .style('opacity', 0)
      .on('mouseover', function(d, i) {
        that.tip.show(d, this);
      })
      .on('mouseout', function(d, i) {
        that.tip.hide(d, this);
      })
      .on('click', function(d) {
        that.show.handleSelectSpan(d);
      });
    nodeEnter
      .append('rect')
      .attr('height', 42)
      .attr('ry',2)
      .attr('rx',2)
      .attr('y', -22)
      .attr('x', 20)
      .attr('width', '100%');
    nodeEnter
      .append('text')
      .attr('x', 13)
      .attr('y', 5)
      .attr('fill', '#E54C17')
      .html(d => d.data.isError?'◉': '')
      nodeEnter
      .append('text')
      .attr('class','node-text')
      .attr('x', 35)
      .attr('y', -6)
      .attr('fill', '#333')
      .text( d => 
        {
          if(d.data.label === 'TRACE_ROOT') {
            return '';
          }
          return   d.data.label.length > 30
          ? `${d.data.label.slice(0, 30)}...`
          : `${d.data.label}`
        }
      );
    nodeEnter
      .append('text')
      .attr('class','node-text')
      .attr('x', 35)
      .attr('y', 12)
      .attr('fill', '#ccc')
      .style('font-size', '11px')
      .text(
        d =>
          `${d.data.layer || ''} ${
            d.data.component ? '- ' + d.data.component : d.data.component || ''
          }`
      );
    nodeEnter
      .append('rect')
      .attr('rx', 2)
      .attr('ry', 2)
      .attr('height', 4)
      .attr('width', d => {
        if (!d.data.endTime || !d.data.startTime) return 0;
        return this.xScale(d.data.endTime- d.data.startTime)+1 || 0;
      })
      .attr('x', d =>
        !d.data.endTime || !d.data.startTime
          ? 0
          : (this.width * 0.618 -
            20 -
            d.y +
            this.xScale(d.data.startTime - this.min)) || 0
      )
      .attr('y', -2)
      .style(
        'fill',
        d => `${this.sequentialScale(this.list.indexOf(d.data.serviceCode))}`
      );
    nodeEnter
      .transition()
      .duration(400)
      .attr('transform', d => `translate(${d.y},${d.x})`)
      .style('opacity', 1);
    nodeEnter
      .append('circle')
      .attr('r', 3)
      .style('cursor', 'pointer')
      .attr('stroke-width', 2.5)
      .attr('fill', d =>
        d._children
          ? `${this.sequentialScale(this.list.indexOf(d.data.serviceCode))}`
          : ''
      )
      .style(
        'stroke',
        d => d.data.label === 'TRACE_ROOT'?'':`${this.sequentialScale(this.list.indexOf(d.data.serviceCode))}`
      )
      .on('click', d => this.click(d, this));
    node
      .transition()
      .duration(400)
      .attr('transform', d => `translate(${d.y},${d.x})`)
      .style('opacity', 1)
      .select('circle')
      .attr('fill', d =>
        d._children
          ? `${this.sequentialScale(this.list.indexOf(d.data.serviceCode))}`
          : ''
      );

    // Transition exiting nodes to the parent's new position.
    node
      .exit()
      .transition()
      .duration(400)
      .attr('transform', `translate(${source.y},${source.x})`)
      .style('opacity', 0)
      .remove();
    const link = this.svg
      .selectAll('.trace-link')
      .data(this.root.links(), function(d) {
        return d.target.id;
      });

    link
      .enter()
      .insert('path', 'g')
      .attr('class', 'trace-link')
      .attr('d', d => {
        const o = { x: source.x0 + 35, y: source.y0 };
        return this.diagonal({ source: o, target: o });
      })
      .transition()
      .duration(400)
      .attr('d', this.diagonal);

    link
      .transition()
      .duration(400)
      .attr('d', this.diagonal);

    link
      .exit()
      .transition()
      .duration(400)
      .attr('d', d => {
        const o = { x: source.x + 35, y: source.y };
        return this.diagonal({ source: o, target: o });
      })
      .remove();
    this.root.each(function(d) {
      d.x0 = d.x;
      d.y0 = d.y;
    });
  }
}
