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

/**
 * data 图数据
 * id 图id
 * height 图高
 * margin {top: 80, right: 20, bottom: 30, left: 60} 外边距
 * titleConfig: { title: '', fontSize: '16px', fontWeight: '700', color: '#000' } 图标题
 * titleYConfig: { title: '', fontSize: '12px', fontWeight: '500', color: '#000' } 图的Y轴标题
 * barValConfig: { fontSize: '14px', fontWeight: '500', color: 'orange' } 柱上文字
 * bgColors: ['#fff'] 用于生成背景柱
 * barColors: ['#8a2be2'] 柱图
 */
const D3SimpleBarChart = (params) => {
  const defaultConfig = {
    margin: {top: 80, right: 20, bottom: 30, left: 60},
    titleConfig: { title: '', fontSize: '16px', fontWeight: '700', color: '#000' },
    titleYConfig: { title: '', fontSize: '12px', fontWeight: '500', color: '#000' },
    barValConfig: { fontSize: '14px', fontWeight: '500', color: 'orange' },
    bgColors: ['#fff'],
    barColors: ['#8a2be2']
  }
  const {
    data,
    id,
    height,
    margin,
    titleConfig,
    titleYConfig,
    barValConfig,
    bgColors,
    barColors
  } = 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 _titleYConfig = setNewValue(titleYConfig, defaultConfig.titleYConfig);
  const _barValConfig = setNewValue(barValConfig, defaultConfig.barValConfig);
  const _bgColors = isArray(bgColors) && bgColors.length ? bgColors : defaultConfig.bgColors;
  const _barColors = isArray(barColors) && barColors.length ? barColors : defaultConfig.barColors;

  let svg = d3.select(`#${id}`)
    .append('svg')
    .attr('width',  width)
    .attr('height', height); 
  // 设置x轴
  let x = d3.scaleBand()
    .rangeRound([0, _width])
    .padding(0.1)
    .domain(
      data.map(function(d) {
        return d.label
      })
    );
  // 设置y轴
  let y = d3.scaleLinear()
    .rangeRound([_height, 0])
    .domain([ 0, d3.max(data, function(d) {
      return d.value
    })]);
  // 用于绘制每条柱
  const barWidth = (_width / data.length) * 0.9;
  // 用于生成背景柱
  const stepArray = d3.ticks(0, d3.max(data, d => d.value), 10);

  // 设置tip
  let tip = d3Tip.default().attr('class', 'd3-tip')
    .offset([-10, 0])
    .html(function(d) {
      const currentData = d.target.__data__;
      return ('<strong>' +currentData.label +"<br>"+_titleYConfig.title+":</strong> <span>" +(currentData.value * 100).toFixed(2) +'%</span>')
    });
  svg.call(tip);
  // 设最外包层在总图上的相对位置
  let g = svg.append('g')
    .attr('transform', 'translate(' + _margin.left + ',' + _margin.top + ')');
  // 设置x轴
  g.append('g')
    .attr('class', 'axis axis--x')
    .attr('transform', 'translate(0,' + _height + ')')
    .call(d3.axisBottom(x));
  // 设置y轴
  g.append('g')
    .attr('class', 'axis axis--y')
    .call(d3.axisLeft(y).ticks(10, '%'))
    .append('text')
    .attr('y', -16)
    .attr('dy', '.71em')
    .style('text-anchor', 'middle')
    .style('fill', _titleYConfig.color)
    .attr('font-size', _titleYConfig.fontSize)
    .attr('font-weight', _titleYConfig.fontWeight)
    .text(`${_titleYConfig.title}`);
  // 设置背景柱
  g.append('g')
    .attr('class', 'bar--bg-bar')
    .selectAll('rect')
    .data(d3.range(stepArray.length - 1))
    .enter()
    .append('rect')
    .attr('stroke', 'none')
    .attr('stroke-width', 0)
    .attr('fill', function(d, i) {
      return _bgColors[i % _bgColors.length]
    })
    .attr('x', 1)
    .attr('width', _width)
    .attr('height', function(d, i) {
      return y(stepArray[i]) - y(stepArray[i + 1])
    })
    .attr('y', function(d, i) {
      return y((i + 1) * stepArray[1])
    });
  // 画柱图
  g.selectAll('.bar')
    .data(data)
    .enter()
    .append('rect')
    .on('mouseover', tip.show)
    .on('mouseout', tip.hide)
    .attr('class', 'bar')
    .attr('fill', function(d, i) {
      return _barColors[i % _barColors.length]
    })
    .attr('x', function(d) {
      return x(d.label)
    })
    .attr('y', _height) // 控制动画由下而上
    .attr('width', x.bandwidth())
    .attr('height', 0) // 控制动画由下而上
    .transition()
    .duration(200)
    .ease(d3.easeBounceInOut)
    .delay(function(d, i) {
      return i * 200
    })
    .attr('y', function(d) {
      return y(d.value)
    })
    .attr('height', function(d) {
      return _height - y(d.value)
    });
  // 输出柱图上的数值
  g.append('g')
    .attr('class', 'bar--text')
    .selectAll('text')
    .data(data)
    .enter()
    .append('text')
    .attr('fill', _barValConfig.color)
    .attr('font-size', _barValConfig.fontSize)
    .attr('font-weight', _barValConfig.fontWeight)
    .attr('text-anchor', 'middle')
    .attr('x', function(d, i) {
      return x(d.label)
    })
    .attr('y', function(d) {
      return y(d.value)
    })
    .attr('dx', barWidth / 2)
    .attr('dy', '1em')
    .text(function(d) {
      return (d.value * 100).toFixed(2) + '%'
    })
    .on('mouseover', tip.show)
    .on('mouseout', tip.hide);
  // 输出标题
  svg.append('g')
    .attr('class', 'bar--title')
    .append('text')
    .attr('fill', _titleConfig.color)
    .attr('font-size', _titleConfig.fontSize)
    .attr('font-weight', _titleConfig.fontWeight)
    .attr('text-anchor', 'middle')
    .attr('x', width / 2)
    .attr('y', 20)
    .text(_titleConfig.title);
}

export default D3SimpleBarChart;