text: /*
   * Line chart options generator
   */
  export default function (dataSource, flatInfo, chartParams) {
    const hasGroups = flatInfo.groups
  
    const {
      xAxis,
      metrics,
      groups,
      xAxisInterval,
      xAxisRotate,
      dataZoomThreshold,
      smooth,
      step,
      symbol,
      tooltip,
      legend,
      toolbox,
      top,
      bottom,
      left,
      right
    } = chartParams
  
    let grouped,
      metricOptions,
      xAxisOptions,
      smoothOption,
      stepOption,
      symbolOption,
      tooltipOptions,
      legendOptions,
      toolboxOptions,
      gridOptions,
      dataZoomOptions
  
    // symbol
    symbolOption = symbol && symbol.length
      ? { symbol: 'emptyCircle' }
      : { symbol: 'none' }
    // smooth
    smoothOption = smooth && smooth.length ? { smooth: true } : null
    // step
    stepOption = step && step.length ? { step: true } : null
  
    // 数据分组
    if (hasGroups && groups && groups.length) {
      grouped = makeGourped(dataSource, [].concat(groups).filter(i => !!i))
    }
  
    // series 数据项； series = metrics * groups
    let metricArr = []
  
    if (metrics) {
      metrics.forEach(m => {
        if (hasGroups && groups && groups.length) {
          Object
            .keys(grouped)
            .forEach(k => {
              let serieObj = Object.assign({},
                {
                  name: `${k} ${m}`,
                  type: 'line',
                  sampling: 'average',
                  data: grouped[k].map(g => g[m])
                },
                symbolOption,
                smoothOption,
                stepOption
              )
              metricArr.push(serieObj)
            })
        } else {
          let serieObj = Object.assign({},
            {
              name: m,
              type: 'line',
              sampling: 'average',
              symbol: symbolOption,
              data: dataSource.map(d => d[m])
            },
            symbolOption,
            smoothOption,
            stepOption
          )
          metricArr.push(serieObj)
        }
      })
      metricOptions = {
        series: metricArr
      }
    }
  
    // x轴数据
    xAxisOptions = xAxis && {
      xAxis: {
        data: hasGroups && groups && groups.length
          ? Object.keys(grouped)
            .map(k => grouped[k])
            .reduce((longest, g) => longest.length > g.length ? longest : g, [])
            .map(item => item[xAxis])
          : dataSource.map(d => d[xAxis]),
        axisLabel: {
          interval: xAxisInterval,
          rotate: xAxisRotate
        }
      }
    }
  
    // tooltip
    tooltipOptions = tooltip && tooltip.length
      ? {
        tooltip: {
          trigger: 'axis'
        }
      } : null
  
    // legend
    legendOptions = legend && legend.length
      ? {
        legend: {
          data: metricArr.map(m => m.name),
          align: 'left',
          top: 3,
          right: 200
        }
      } : null
  
    // toolbox
    toolboxOptions = toolbox && toolbox.length
      ? {
        toolbox: {
          feature: {
            dataZoom: {
              yAxisIndex: 'none'
            },
            restore: {},
            saveAsImage: {
              pixelRatio: 2
            }
          },
          right: 22
        }
      } : null
  
    // grid
    gridOptions = {
      grid: {
        top: top,
        left: left,
        right: right,
        bottom: bottom
      }
    }
  
    dataZoomOptions = dataZoomThreshold > 0 && dataZoomThreshold < dataSource.length && {
      dataZoom: [{
        type: 'inside',
        start: Math.round((1 - dataZoomThreshold / dataSource.length) * 100),
        end: 100
      }, {
        start: Math.round((1 - dataZoomThreshold / dataSource.length) * 100),
        end: 100,
        handleIcon: 'M10.7,11.9v-1.3H9.3v1.3c-4.9,0.3-8.8,4.4-8.8,9.4c0,5,3.9,9.1,8.8,9.4v1.3h1.3v-1.3c4.9-0.3,8.8-4.4,8.8-9.4C19.5,16.3,15.6,12.2,10.7,11.9z M13.3,24.4H6.7V23h6.6V24.4z M13.3,19.6H6.7v-1.4h6.6V19.6z',
        handleSize: '80%',
        handleStyle: {
          color: '#fff',
          shadowBlur: 3,
          shadowColor: 'rgba(0, 0, 0, 0.6)',
          shadowOffsetX: 2,
          shadowOffsetY: 2
        }
      }]
    }
  
    return Object.assign({},
      {
        yAxis: {
          type: 'value'
        }
      },
      metricOptions,
      xAxisOptions,
      tooltipOptions,
      legendOptions,
      toolboxOptions,
      gridOptions,
      dataZoomOptions
    )
  }
  
  export function makeGourped (dataSource, groupColumns) {
    return dataSource.reduce((acc, val) => {
      let accColumn = groupColumns
        .reduce((arr, col) => {
          arr.push(val[col])
          return arr
        }, [])
        .join(' ')
      if (!acc[accColumn]) {
        acc[accColumn] = []
      }
      acc[accColumn].push(val)
      return acc
    }, {})
  }
  