/** 原 HistoryEchart，自定义页面中常用的 ECharts 组件 */
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import { Checkbox } from 'antd'
import { IFComponent } from '@woowalker/feui'
import TableChart from './TableChart'
import { set } from 'lodash'

/** 最大值标线 */
const maxLine = {
  type: 'max',
  label: {
    formatter: '最大值: {c}'
  },
  lineStyle: {
    color: '#1abfbb'
  }
}

/** 最小值标线 */
const minLine = {
  type: 'min',
  label: {
    formatter: '最小值: {c}'
  },
  lineStyle: {
    color: '#f7774a'
  }
}

/** 平均值标线 */
const avgLine = {
  type: 'average',
  label: {
    formatter: '平均值: {c}'
  },
  lineStyle: {
    color: '#f9517d'
  }
}

class CommonChart extends Component {
  constructor (props) {
    super(props)
    this.state = {
      checkedValue: []
    }
  }

  // 初始化 option
  initOption = () => {
    const { xAxis, yAxis, data, rotateXAxisLabel, titleText, saveImgName, magicType } = this.props

    // 设置图例的默认选中，如果没有 Selected 属性，则默认为 true，即默认选中
    const legendData = []
    const selectedData = {}
    data.forEach(item => {
      legendData.push({ name: item.Name, icon: item.LegendIcon || '' })
      selectedData[item.Name] = item.LegendSelected !== undefined ? item.LegendSelected : true
    })

    return {
      title: {
        text: titleText,
        textStyle: {
          fontWeight: 'normal',
          fontSize: 16
        },
        left: 'center',
        top: 0
      },
      legend: {
        type: 'scroll',
        top: '8%',
        textStyle: {
          color: '#333333'
        },
        data: legendData,
        selected: selectedData
      },
      grid: {
        top: '26%',
        left: '2%',
        right: '6%',
        bottom: '2%',
        containLabel: true
      },
      // xAxis 要么为空数组，要么 data 必须有值，否则 echarts 本身会报错
      xAxis: xAxis.length ? [
        {
          type: 'category',
          axisLabel: {
            rotate: rotateXAxisLabel && xAxis.length > 10 ? -20 : 0
          },
          data: xAxis
        }
      ] : [],
      // xAxis data 必须有值，否则 echarts 本身会报错
      yAxis: xAxis.length ? yAxis.map((item, index) => {
        const { Name: name, Max: max, Min: min, IsInverse: inverse } = item
        return {
          type: 'value',
          name,
          nameTextStyle: { align: 'left' },
          max: max || undefined,
          min,
          inverse,
          splitLine: {
            show: index === 0 // 右侧Y轴不显示分割线
          },
          position: index === 0 ? 'left' : 'right',
          offset: index === 0 ? 0 : (1 - index) * 50
        }
      }) : [],
      // xAxis data 必须有值，否则 echarts 本身会报错
      dataZoom: xAxis.length ? [
        {
          type: 'inside',
          xAxisIndex: [0]
        }
      ] : [],
      // 折线图颜色分段显示
      visualMap: [],
      tooltip: {
        trigger: 'axis',
        axisPointer: {
          type: 'shadow'
        },
        formatter: (params) => {
          const title = params[0].axisValueLabel
          const body = params.map(item => {
            return `<div>${item.marker}${item.seriesName}：<span>${item.data.TooltipValue || item.data.value}</span></div>`
          }).join('')
          return `<div><div>${title}</div>${body}</div>`
        }
      },
      toolbox: {
        show: true,
        orient: 'vertical',
        right: 0,
        top: 'center',
        itemSize: 12,
        feature: {
          magicType: { show: true, type: magicType },
          restore: { show: true },
          saveAsImage: { show: true, name: saveImgName || titleText }
        }
      },
      series: []
    }
  }

  // 生成 echarts 所需要 option
  getOption = () => {
    const option = this.initOption()
    // xAxis data 必须有值，否则 echarts 本身会报错
    if (!option.xAxis.length) return option

    // 组装 option.series 数据
    const { checkedValue } = this.state
    const { data, markLineMax, markLineMin, markLineAvg } = this.props

    data.forEach((item, index) => {
      const dataseries = {
        name: item.Name,
        type: item.Type || 'bar', // 默认柱状图
        yAxisIndex: item.YAxisIndex || 0, // 默认对应第一条Y轴
        stack: item.Stack,
        itemStyle: {
          color: item.Color || ''
        },
        markLine: {
          silent: true,
          symbol: 'none',
          label: {
            position: 'insideStartTop',
            distance: [10, 4]
          },
          lineStyle: {
            width: 2
          },
          data: []
        },
        data: item.Data.map(element => {
          // 在需要最大最小标线的图中，去掉 0 值
          return {
            value: (markLineMax || markLineMin) && element.Value == 0 ? undefined : element.Value,
            TooltipValue: element.TooltipValue
          }
        })
      }
      // 标记最大、最小、平均值（右侧Y轴的最大、最小、平均值不显示）
      if ((markLineMax || markLineMin) && item.YAxisIndex === 0) {
        markLineMax && checkedValue.indexOf('Max') !== -1 && dataseries.markLine.data.push(maxLine)
        markLineMin && checkedValue.indexOf('Min') !== -1 && dataseries.markLine.data.push(minLine)
        markLineAvg && dataseries.markLine.data.push(avgLine)
      }
      // 图表配置
      switch (item.Type) {
        // 折线图配置
        case 'line':
          dataseries.symbol = 'circle'
          // 折线图线条类型：solid dashed dotted
          item.LineType && (dataseries.lineStyle = { type: item.LineType })
          // 折线图分段显示
          item.Pieces && option.visualMap.push({
            show: false,
            dimension: 0,
            seriesIndex: index,
            pieces: item.Pieces
          })
          /**
           * 分段显示的折线图区域显示各段颜色，配置举例如下
           * const PiecesOption = { 'symbol': 'none', 'lineStyle.color': '#2f54eb', 'areaStyle': {} }
           */
          if (item.PiecesOption) {
            Object.keys(item.PiecesOption).forEach(key => {
              set(dataseries, key, item.PiecesOption[key])
            })
            set(dataseries, 'lineStyle.color', item.Color)
          }
          break
        // 散点图配置
        case 'scatter':
          dataseries.symbolSize = 15
          break
        //默认为柱状图配置
        default:
          dataseries.barMaxWidth = 30
          break
      }
      option.series.push(dataseries)
    })

    return option
  }

  render () {
    const { markLineMax, markLineMin, onClick, onMouseover, loading, style } = this.props
    const markLineOptions = []
    markLineMax && markLineOptions.push({ label: '最大值', value: 'Max' })
    markLineMin && markLineOptions.push({ label: '最小值', value: 'Min' })
    return (
      <TableChart
        chartId={this.props.chartId}
        option={this.getOption()}
        onEvents={{
          click: onClick instanceof Function && onClick,
          mouseover: onMouseover instanceof Function && onMouseover
        }}
        loading={loading}
        style={style}
      >
        <IFComponent IF={markLineMax || markLineMin}>
          <Checkbox.Group
            options={markLineOptions}
            defaultValue={this.state.checkedValue}
            onChange={(checkedValue) => this.setState({ checkedValue })}
            style={{ marginRight: 10 }}
          />
        </IFComponent>
      </TableChart>
    )
  }
}

CommonChart.propTypes = {
  xAxis: PropTypes.array,
  yAxis: PropTypes.array,
  data: PropTypes.array,
  markLineMax: PropTypes.bool,
  markLineMin: PropTypes.bool,
  markLineAvg: PropTypes.bool,
  rotateXAxisLabel: PropTypes.bool,
  titleText: PropTypes.string,
  saveImgName: PropTypes.string,
  magicType: PropTypes.array,
  chartId: PropTypes.string,
  onClick: PropTypes.func,
  onMouseover: PropTypes.func
}

CommonChart.defaultProps = {
  xAxis: [], // x 轴数据
  yAxis: [], // y 轴数据
  data: [], // 图表数据
  markLineMax: false, // 是否显示最大值标线
  markLineMin: false, // 是否显示最小值标线
  markLineAvg: false, // 是否显示平均值标线
  rotateXAxisLabel: false, // 是否旋转X轴标签
  titleText: '', // 图表 top center 位置的标题
  saveImgName: '', // 导出为图片的图片文件名称
  magicType: ['line', 'bar', 'stack'], // 图表工具
  chartId: '', // 目标值设定所需的唯一性固定ID
  onClick: null, // 图表节点点击事件
  onMouseover: null // 图表节点鼠标移上事件
}

export default CommonChart