// 核心库
import React, { Component } from 'react'
import { connect } from 'dva'
import PropTypes from 'prop-types'
// 组件库
import ReactEcharts from "echarts-for-react"
import { Popover, Table, Icon, Spin, Input, message } from 'antd'
import { ExportToExcel, IFComponent } from '@woowalker/feui'
// 工具库
import { isEqual } from 'lodash'
import { uuid, initFilter } from '../../utils/common'
// 样式
import classNames from 'classnames'
import styles from './chart.css'

class TableChart extends Component {
  constructor (props) {
    super(props)
    this.state = {
      data: [],
      columns: [],
      toggleChart: false,
      // 用于列表导出的 id
      tableId: uuid(),
      // 设定的参考目标值
      targetVal: undefined
    }
    this.refOfChart = null
  }

  componentDidMount () {
    const { option, type, chartId } = this.props
    if (option) {
      this.getTableData(option, type)
      chartId && this.getTargetVal()
    }
  }

  UNSAFE_componentWillReceiveProps (nextProps) {
    if (!isEqual(this.props.option, nextProps.option)) {
      this.getTableData(nextProps.option, nextProps.type)
    }
  }

  /** 生成 table 数据 */
  getTableData = (option, type) => {
    const data = []
    const columns = []
    const { radar, series = [], xAxis = [], yAxis = [] } = option
    switch (type) {
      // 饼图
      case 2:
        if (series[0] && Array.isArray(series[0].data) && series[0].data.length) {
          // 从 series 取 columns
          let total = 0
          series[0].data.forEach(({ name, value }) => {
            total += value
            columns.push({ title: name, dataIndex: name, key: name })
          })
          // 从 series 取 data
          const tempTableData = {}
          series[0].data.forEach(({ name, value }) => {
            tempTableData[name] = `${value}(${total ? (value / total * 100).toFixed(2) : 0}%)`
          })
          data.push(tempTableData)
        }
        break
      // 雷达图
      case 3:
        if (radar[0] && Array.isArray(radar[0].indicator) && radar[0].indicator.length) {
          columns.push({ title: '类型', dataIndex: 'name', key: 'name' })
          // 从 radar 取 columns
          radar[0].indicator.forEach(item => columns.push({ title: `${item.text}(${item.max})`, dataIndex: item.text, key: item.text }))
          // 从 series 取 data
          series.forEach(serie => {
            const tempTableData = {}
            columns.forEach((item, index) => {
              const { name, data: serieData } = serie
              tempTableData[item.key] = item.title === '类型' ? name : serieData[0].value[index - 1]
            })
            data.push(tempTableData)
          })
        }
        break
      // 折线、柱状图
      default:
        if (xAxis[0] && Array.isArray(xAxis[0].data) && xAxis[0].data.length) {
          columns.push({ title: '类型', dataIndex: 'name', key: 'name' })
          // 从 xAxis 取 columns
          xAxis[0].data.forEach(item => columns.push({ title: item, dataIndex: item, key: item }))
          // 从 series 取 data
          series.forEach(serie => {
            const tempTableData = {}
            columns.forEach((item, index) => {
              const { name, data: serieData, yAxisIndex } = serie
              const yName = (yAxis[yAxisIndex || 0] || {}).name
              tempTableData[item.key] = item.title === '类型' ? `${name}${yName ? '(' + yName + ')' : ''}` : (serieData[index - 1]?.TooltipValue || serieData[index - 1]?.value)
            })
            data.push(tempTableData)
          })
        }
    }
    this.setState({ data, columns })
  }

  /** 获取 chartId 对应的目标值 */
  getTargetVal = () => {
    const { chartId, login, dispatch } = this.props
    const json = initFilter(login.OrgId, chartId)
    dispatch({
      type: 'app/getRedisValue',
      payload: json
    }).then(res => {
      this.setState({ targetVal: isNaN(res) ? res : Number(res) })
    })
  }

  /** 设置 chartId 对应的目标值 */
  setTargetVal = (value) => {
    const { chartId, login, dispatch } = this.props
    const json = initFilter(login.OrgId, chartId)
    json.Parameter1 = value
    dispatch({
      type: 'app/setRedisValue',
      payload: json
    }).then(res => {
      if (res) {
        this.setState({ targetVal: isNaN(value) ? value : Number(value) })
        message.success('操作成功')
      }
    })
  }

  /** 处理目标值 targetVal 的修改 */
  handleTVChange = (evt) => {
    const { value } = evt.target
    const targetVal = value === '' ? '' : isNaN(value) ? value : Number(value)
    this.setState({ targetVal })
  }

  getChartOption = (option) => {
    const { targetVal } = this.state
    if (Array.isArray(option.series) && option.series.length && targetVal) {
      if (Array.isArray(option.yAxis) && option.yAxis.length) {
        // 标记线默认对应的Y轴就是第一条Y轴，所以这里默认取第一条Y轴进行设置
        const { max, min } = option.yAxis[0]
        let maxSet = false
        let minSet = false
        // 监测对应 max 值是否小于 targetVal 值
        if (max) {
          maxSet = max < targetVal
        } else {
          // 取对应默认第一条Y轴的数据，取其最大值
          const targetSeries = option.series.filter(item => item.yAxisIndex === 0)
          const maxData = Math.max.apply(null, targetSeries.map(item => Math.max.apply(null, item.data)))
          maxSet = maxData < targetVal
        }
        // 监测对应 min 值是否大于 targetVal 值
        minSet = min > targetVal
        // 设置 targetVal 对应的 max 和 min 值
        maxSet && (option.yAxis[0].max = targetVal)
        minSet && (option.yAxis[0].min = targetVal)
      }
      return {
        ...option,
        series: [
          {
            name: '标记线',
            type: 'line',
            markLine: {
              label: {
                position: 'insideEndTop',
                formatter: '{b}: {c}'
              },
              lineStyle: {
                color: '#096dd9'
              },
              data: [
                {
                  name: '目标值',
                  yAxis: targetVal,
                  lineStyle: { width: 2 }
                }
              ]
            }
          }
        ].concat(option.series)
      }
    }
    return option
  }

  render () {
    const { chartId, option, onEvents, loading, style } = this.props

    const { targetVal, data, columns, toggleChart } = this.state
    const loadingGet = this.props.dvaLoading.effects['app/getRedisValue']
    const loadingSet = this.props.dvaLoading.effects['app/setRedisValue']
    return (
      <Spin size='large' spinning={!!loading} wrapperClassName={styles.chartTable}>
        <div className={styles.chartTableSwap}>
          {/** 额外需要插入的工具集 */}
          {this.props.children}
          {/** 目标值设定 */}
          <IFComponent IF={!toggleChart && !!chartId}>
            <Popover
              content={
                <Input.Search
                  autoFocus
                  allowClear
                  value={targetVal}
                  loading={loadingGet || loadingSet}
                  placeholder='请输入设定目标值'
                  enterButton='保存'
                  onChange={this.handleTVChange}
                  onSearch={this.setTargetVal}
                />
              }
              trigger='click'
            >
              <Icon type='setting' title='目标值设定' style={{ marginRight: 10 }} />
            </Popover>
          </IFComponent>
          {/** 图形列表切换按钮 */}
          <span onClick={() => { this.setState({ toggleChart: !toggleChart }) }}>
            <Icon type='swap' />
            <span>{`切换${toggleChart ? '图表' : '列表'}`}</span>
          </span>
          {/** 导出按钮 */}
          <IFComponent IF={toggleChart}>
            <ExportToExcel
              fileName='列表数据'
              tableId={this.state.tableId}
              render={({ onExport }) => <Icon type='download' title='导出' onClick={onExport} style={{ paddingLeft: 10 }} />}
            />
          </IFComponent>
        </div>
        <ReactEcharts
          ref={ref => this.refOfChart = ref?.getEchartsInstance()}
          notMerge
          lazyUpdate
          option={this.getChartOption(option)}
          onEvents={onEvents}
          className={classNames(styles.chart, { [styles.show]: !toggleChart, [styles.hide]: toggleChart })}
          style={{ width: '100%', height: '100%', ...style }}
        />
        <Table
          id={this.state.tableId}
          bordered
          rowKey='ID'
          size='small'
          dataSource={data}
          columns={columns}
          scroll={{ x: true }}
          pagination={false}
          className={classNames(styles.table, { [styles.show]: toggleChart, [styles.hide]: !toggleChart })}
        />
      </Spin>
    )
  }
}

TableChart.propTypes = {
  option: PropTypes.object,
  type: PropTypes.string,
  chartId: PropTypes.string,
  onEvents: PropTypes.object,
  style: PropTypes.object
}

export default connect(({ login, loading }) => ({ login, dvaLoading: loading }))(TableChart)
