import * as d3 from 'd3';
import { isFun, setNewValue } from '../../../utils/util';

var _currentData = null;

/**
 * data 图数据
 * id 图id
 * height 图高 600
 * margin { top: 80, right: 60, bottom: 80, left: 60 }
 * titleConfig: { title: '', fontSize: '14px', fontWeight: '700', color: '#fff' } 标题
 * percentConfig: { fontSize: '14px', fontWeight: '700', color: '#cddc39' } 百分比
 * colors 颜色配置 例如：['#98abc5', '#8a89a6', '#7b6888', '#6b486b', '#a05d56', '#d0743c', '#ff8c00' ]
 * lineColor #999 线条颜色
 * labelConfig: { fontSize: '12px', fontWeight: '500', color: '#000' } label文字配置
 * formatFun 格式化函数
 */
const D3SimplePieChart = (params) => {
  const defaultConfig = {
    margin: { top: 80, right: 60, bottom: 80, left: 60 },
    titleConfig: { title: '', fontSize: '14px', fontWeight: '700', color: '#fff' },
    percentConfig: { fontSize: '14px', fontWeight: '700', color: '#cddc39' },
    colors: ['#98abc5', '#8a89a6', '#7b6888', '#6b486b', '#a05d56', '#d0743c', '#ff8c00' ],
    lineColor: '#999',
    labelConfig: { fontSize: '12px', fontWeight: '500', color: '#000' }
  }
  const {
    data,
    id,
    height,
    margin,
    titleConfig,
    formatFun,
    colors,
    percentConfig,
    lineColor,
    labelConfig
  } = params;

  const container = document.getElementById(`${id}`);
  if (!container) return;
  _currentData = null;

  const width = container.offsetWidth;
  const _margin = setNewValue(margin, defaultConfig.margin);
  
  const _width = width - _margin.left - _margin.right;
  const _height = height - _margin.top - _margin.bottom;

  const setColors = colors || defaultConfig.colors;
  const _titleConfig = setNewValue(titleConfig, defaultConfig.titleConfig);
  const _percentConfig = setNewValue(percentConfig, defaultConfig.percentConfig);
  const _labelConfig = setNewValue(labelConfig, defaultConfig.labelConfig);

  // 设置总宽高
  let svg = d3.select(`#${id}`)
    .append('svg')
    .attr('width',  width)
    .attr('height', height);
  
  const radius = Math.min(_width, _height) / 2;

  let g = svg.append('g')
    .attr('transform', 'translate(' +(_width / 2 + _margin.left) +',' +(_margin.top + radius) +')'); // 设最外包层在总图上的相对位置

  let _colors = d3.scaleOrdinal().range(setColors);
  // 定义单个圆弧
  let arc = d3.arc()
    .innerRadius(0)
    .padAngle(0);
  // 定义单个圆弧里面的线条开始点所在的弧
  let startPointArc = d3.arc()
    .outerRadius(radius - 10)
    .innerRadius(radius - 10);
  // 定义单个圆弧里面的percent文字
  let percentLabelArc = d3.arc()
    .outerRadius(radius - 60)
    .innerRadius(radius - 60);
  // 定义单个圆弧里面的value文字
  let valueLabelArc = d3.arc() 
    .outerRadius(radius + 40)
    .innerRadius(radius + 40);
  // 定义饼图
  let pie = d3.pie()
    .sort(null)
    .value(function(d) {
      return d.value
    });
  const sumData = d3.sum(data, function(d) {
    return d.value
  });
  // 定义颜色值域
  _colors.domain(
    d3.map(data, function(d) {
      return d.label
    })
    .keys()
  );
  g.selectAll('.arc') // 画环图
    .data(pie(data))
    .enter()
    .append('path')
    .attr('cursor', 'pointer')
    .attr('class', 'arc')
    .attr('stroke', function(d) {
      return _colors(d.data.label)
    })
    .style('fill', function(d) {
      return _colors(d.data.label)
    })
    .each(function(d) {
      // 储存当前起始与终点的角度、并设为相等
      let tem = { ...d, endAngle: d.startAngle }
      d.outerRadius = radius - 10
      _currentData = tem
    })
    .on('mouseover', arcTween(radius + 20, 0))
    .on('mouseout', arcTween(radius - 10, 150))
    .transition()
    .duration(100)
    .delay(function(d, i) {
      return i * 100
    })
    .attrTween('d', function(next) {
      // 动态设置d属性、生成动画
      var i = d3.interpolate(_currentData, next)
      _currentData = i(0) // 重设当前角度
      return function(t) {
        return arc(i(t))
      }
    });

    const arcs = pie(data); // 构造圆弧

    let linkLine = g.append('g'); // 创建每条连接线
    let links = [];
    arcs.forEach(function(d) {
      // 输出label文字
      const startPoint = startPointArc.centroid(d)
      const endPoint = valueLabelArc.centroid(d)
      links.push({
        source: [startPoint[0], startPoint[1]],
        target: [endPoint[0], endPoint[1]]
      })
    });
    linkLine.selectAll()
      .data(links)
      .enter()
      .append('path')
      .attr('class', 'link-line')
      .style('stroke', lineColor || defaultConfig.lineColor)
      .style('stroke-width', 1)
      .attr('fill', 'none')
      .attr('d', d3.linkHorizontal()
        .source(function(d) {
          return d.source
        })
        .target(function(d) {
          return d.target
        })
      );
    let label = g.append('g');
    arcs.forEach(function(d) {
      // 输出percent文字
      const c = percentLabelArc.centroid(d);
      label.append('text')
        .attr('class', 'label-text')
        .attr('fill', _percentConfig.color)
        .attr('font-weight', _percentConfig.fontWeight)
        .attr('font-size', _percentConfig.fontSize)
        .attr('text-anchor', 'middle')
        .attr('x', c[0])
        .attr('y', c[1])
        .text(((d.data.value * 100) / sumData).toFixed(1) + '%');
    });
    arcs.forEach(function(d) {
      // 输出value文字
      var c = valueLabelArc.centroid(d);
      label.append('text')
        .attr('class', 'label-text')
        .attr('fill', _labelConfig.color)
        .attr('font-weight', _labelConfig.fontWeight)
        .attr('font-size', _labelConfig.fontSize)
        .attr('text-anchor', function(d) {
          return c[0] >= 0 ? 'start' : 'end'
        })
        .attr('x', c[0])
        .attr('y', c[1])
        .text(isFun(formatFun) ? formatFun(d.data) : `${d.data.label}  : ${d.data.value}`);
    });
    svg.append('g') // 输出标题
      .attr('class', 'arc--title')
      .append('text')
      .attr('fill', _titleConfig.color)
      .attr('font-size', _titleConfig.fontSize)
      .attr('font-weight', _titleConfig.fontWeight)
      .attr('transform', 'translate(' +(_width / 2 + _margin.left)+','+(_margin.top + radius) +')')
      .attr('text-anchor', 'middle')
      .attr('x', 0)
      .attr('y', 0)
      .text(_titleConfig.title);
    function arcTween(outerRadius, delay) {
      // 设置缓动函数
      return function() {
        d3.select(this)
          .transition()
          .delay(delay)
          .attrTween('d', function(d) {
            var i = d3.interpolate(d.outerRadius, outerRadius)
            return function(t) {
              d.outerRadius = i(t)
              return arc(d)
            }
          })
      }
    }
}

export default D3SimplePieChart;