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

/**
 * data 图数据
 * id 图id
 * height 图高 例如：500
 * margin 例如：{ top: 80, right: 60, bottom: 80, left: 60 }
 * names 数据字段说明 例如：{ apple: '苹果', banana: '香蕉' }
 * titleConfig: { title: '', fontSize: '14px', fontWeight: '700', color: '#000' } 标题
 * valConfig: { fontSize: '12px', fontWeight: '500', color: '#000', padding: 3 } 数据标签样式
 * labelConfig: { fontSize: '12px', fontWeight: '500', color: '#000' } 分类标签样式
 * formatValFun 格式化value函数
 */
const D3SimpleLineChart = (params) => {
  const defaultConfig = {
    margin: { top: 80, right: 60, bottom: 80, left: 60 },
    titleConfig: { title: '', fontSize: '14px', fontWeight: '700', color: '#000' },
    labelConfig: { fontSize: '12px', fontWeight: '500', color: '#000' },
    valConfig: { fontSize: '12px', fontWeight: '500', color: '#000', padding: 3 }
  }
  const {
    data,
    id,
    height,
    margin,
    names,
    titleConfig,
    formatValFun,
    colors,
    labelConfig,
    valConfig
  } = params;

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

  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 _titleConfig = setNewValue(titleConfig, defaultConfig.titleConfig);
  const _labelConfig = setNewValue(labelConfig, defaultConfig.labelConfig);
  const _valConfig = setNewValue(valConfig, defaultConfig.valConfig);

  // 设置总宽高
  let svg = d3.select(`#${id}`)
    .append('svg')
    .attr('width',  width)
    .attr('height', height);

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

  const keys = Object.keys(names);

  const series = d3.map(Object.keys(data[0]), function (d) {
    return d
  }).slice(1)
    .map(function (key) {
      // 生成两条线的数组
      return data.map(function (d) {
        return {
          key: key,
          date: d3.timeParse('%Y')(d.label),
          value: d[key]
        }
      })
    });

  let x = d3.scaleTime() // 定义x轴
    .domain([
      d3.timeParse('%Y')(data[0].label),
      d3.timeParse('%Y')(data[data.length - 1].label)
    ])
    .range([0, _width]);

  let y = d3.scaleLinear() // 定义y轴
    .domain([0, d3.max(series, function (s) {
        return d3.max(s, function (d) {
          return d.value
        })
      })
    ])
    .range([_height, 0]);

  let z = d3.scaleOrdinal(d3.schemeCategory10) // 通用线条的颜色

  let line = d3.line()
    .x(function (d) {
      return x(d.date)
    })
    .y(function (d) {
      return y(d.value)
    });

  svg.append('defs')
    .append('clipPath') // 添加长方形方块，遮罩作用
    .attr('id', 'clip')
    .append('rect')
    .attr('height', _height)
    .attr('width', 0) // 用遮罩实现线动画
    .transition()
    .duration(1000)
    .attr('width', _width);

  g.append('g') // 生成x轴
    .attr('class', 'axis axis--x')
    .attr('transform', 'translate(0,' + _height + ')')
    .call(d3.axisBottom(x).tickFormat(d3.timeFormat('%Y年')));

  let serie = g.selectAll('.serie') // 生成两线条
    .data(series)
    .enter()
    .append('g')
    .attr('class', 'serie');

  serie.append('path') // 绘画线条
    .attr('clip-path', 'url(#clip)')
    .attr('class', 'line')
    .style('stroke', function (d) {
      const idx = keys.indexOf(d[0].key)
      return isArray(colors) && colors[idx] ? colors[idx] : z(d[0].key)
    })
    .attr('fill', 'none')
    .attr('d', line);

  let label = serie.selectAll('.label') // 生成文字包层
    .data(function (d) {
      return d
    })
    .enter()
    .append('g')
    .attr('class', 'label')
    .attr('transform', function (d, i) {
      return 'translate(' + x(d.date) + ',' + y(d.value) + ')'
    });

  label.append('text') // 生成数值文字
    .attr('dy', '.35em')
    .attr('fill', _valConfig.color)
    .attr('font-size', _valConfig.fontSize)
    .attr('font-weight', _valConfig.fontWeight)
    .text(function (d) {
      return isFun(formatValFun) ? formatValFun(d) : d.value
    })
    .filter(function (d, i) {
      return i === data.length - 1
    })
    .append('tspan') // 生成名文字
    .attr('class', 'label-key')
    .attr('fill', _labelConfig.color)
    .attr('font-weight', _labelConfig.fontWeight)
    .attr('font-size', _labelConfig.fontSize)
    .text(function (d) {
      return ' ' + names[d.key]
    });

  label.insert('rect', 'text') // 生成背景白块
    .datum(function () {
      return this.nextSibling.getBBox()
    })
    .attr('fill', '#fff')
    .attr('x', function (d) {
      return d.x - _valConfig.padding
    })
    .attr('y', function (d) {
      return d.y - _valConfig.padding
    })
    .attr('width', function (d) {
      return d.width + 2 * _valConfig.padding
    })
    .attr('height', function (d) {
      return d.height + 2 * _valConfig.padding
    });

  svg.append('g') // 输出标题
    .attr('class', 'line-title')
    .append('text')
    .attr('fill', _titleConfig.color)
    .attr('font-weight', _titleConfig.fontWeight)
    .attr('font-size', _titleConfig.fontSize)
    .attr('transform','translate(' + (_width / 2 + _margin.left) + ',' + 20 + ')')
    .attr('text-anchor', 'middle')
    .attr('x', 0)
    .attr('y', 0)
    .text(_titleConfig.title);
}

export default D3SimpleLineChart
