import {
  G2PlotChartView,
  G2PlotDrawOptions
} from '@/views/chart/components/js/panel/types/impl/g2plot'
import type { Liquid as G2Liquid, LiquidOptions } from '@antv/g2plot/esm/plots/liquid'
import { flow, hexColorToRGBA, parseJson } from '@/views/chart/components/js/util'
import { DEFAULT_MISC } from '@/views/chart/components/editor/util/chart'
import { valueFormatter } from '@/views/chart/components/js/formatter'
import { useI18n } from '@/hooks/web/useI18n'
import { defaultsDeep } from 'lodash-es'

const { t } = useI18n()
const DEFAULT_LIQUID_DATA = []
/**
 * 水波图
 */
export class Liquid extends G2PlotChartView<LiquidOptions, G2Liquid> {
  properties: EditorProperty[] = [
    'background-overall-component',
    'border-style',
    'basic-style-selector',
    'label-selector',
    'misc-selector',
    'title-selector',
    'threshold'
  ]
  propertyInner: EditorPropertyInner = {
    'background-overall-component': ['all'],
    'border-style': ['all'],
    'basic-style-selector': ['colors', 'alpha'],
    'label-selector': ['fontSize', 'color', 'showQuota', 'showProportion'],
    'misc-selector': [
      'liquidShape',
      'liquidSize',
      'liquidMaxType',
      'liquidMaxField',
      'liquidShowBorder',
      'liquidBorderWidth',
      'liquidBorderDistance'
    ],
    'title-selector': [
      'title',
      'fontSize',
      'color',
      'hPosition',
      'isItalic',
      'isBolder',
      'remarkShow',
      'fontFamily',
      'letterSpace',
      'fontShadow'
    ],
    threshold: ['liquidThreshold']
  }
  axis: AxisType[] = ['yAxis', 'filter']
  axisConfig: AxisConfig = {
    yAxis: {
      name: `${t('chart.drag_block_progress')} / ${t('chart.quota')}`,
      type: 'q',
      limit: 1
    }
  }

  async drawChart(drawOptions: G2PlotDrawOptions<G2Liquid>): Promise<G2Liquid> {
    const { chart, container, action } = drawOptions
    if (!chart.data?.series || !chart.yAxis.length) {
      return
    }
    const initOptions: LiquidOptions = {
      percent: 0
    }
    const options = this.setupOptions(chart, initOptions)
    const { Liquid: G2Liquid } = await import('@antv/g2plot/esm/plots/liquid')
    const newChart = new G2Liquid(container, options)
    newChart.on('afterrender', () => {
      action({
        from: 'liquid',
        data: {
          type: 'liquid',
          max: chart.data?.series[0]?.data[0]
        }
      })
    })
    // 处理空数据, 只要有一个指标是空数据，就不显示图表
    const hasNoneData = chart.data?.series.some(
      s => s.data?.[0] === undefined || s.data?.[0] === null
    )
    this.configEmptyDataStyle(hasNoneData ? [] : [1], container, newChart)
    if (hasNoneData) {
      return
    }
    return newChart
  }

  protected configTheme(chart: Chart, options: LiquidOptions): LiquidOptions {
    const customAttr = parseJson(chart.customAttr)
    const colors: string[] = []
    if (customAttr.basicStyle) {
      const basicStyle = customAttr.basicStyle
      basicStyle.colors.forEach(ele => {
        colors.push(hexColorToRGBA(ele, basicStyle.alpha))
      })
    }
    const customStyle = parseJson(chart.customStyle)
    let bgColor
    if (customStyle.background) {
      bgColor = hexColorToRGBA(customStyle.background.color, customStyle.background.alpha)
    }
    const theme = {
      styleSheet: {
        brandColor: colors[0],
        paletteQualitative10: colors,
        paletteQualitative20: colors,
        backgroundColor: bgColor
      }
    }
    return { ...options, theme }
  }

  protected configMisc(chart: Chart, options: LiquidOptions): LiquidOptions {
    const customAttr = parseJson(chart.customAttr)
    let value = 0
    if (chart.data.series.length > 0) {
      value = chart.data.series[0].data[0]
    }
    let max, radius, shape
    if (customAttr.misc) {
      const misc = customAttr.misc
      const defaultLiquidMax = chart.data?.series[chart.data?.series.length - 1]?.data[0]
      if (misc.liquidMaxType === 'dynamic') {
        max = defaultLiquidMax
      } else {
        max = misc.liquidMax ? misc.liquidMax : defaultLiquidMax
      }
      radius = (misc.liquidSize ? misc.liquidSize : DEFAULT_MISC.liquidSize) / 100
      shape = misc.liquidShape ?? DEFAULT_MISC.liquidShape
    }
    const size: LiquidOptions = {
      percent: value / max,
      radius: radius,
      shape: shape
    }
    const { misc } = customAttr
    if (misc?.liquidShowBorder) {
      defaultsDeep(size, {
        outline: {
          border: misc.liquidBorderWidth ?? DEFAULT_MISC.liquidBorderWidth,
          distance: misc.liquidBorderDistance ?? DEFAULT_MISC.liquidBorderDistance
        }
      })
    }
    return { ...options, ...size }
  }

  protected configLabel(chart: Chart, options: LiquidOptions): LiquidOptions {
    const customAttr = parseJson(chart.customAttr)
    const originVal = options.percent
    // 数值过大图表会异常，大于 1 无意义
    if (originVal > 1) {
      options = {
        ...options,
        percent: 1
      }
    }
    if (!customAttr.label?.show) {
      return {
        ...options,
        statistic: {
          content: false
        }
      }
    }
    const label = customAttr.label
    const style = {
      fontSize: label.fontSize.toString() + 'px',
      color: label.color,
      lineHeight: '"unset"',
      overflow: 'visible',
      opacity: 1
    }
    const title = label.showQuota
      ? {
          style,
          formatter: () => {
            return valueFormatter(chart.data.series[0].data[0], label.quotaLabelFormatter)
          }
        }
      : false
    const content = label.showProportion
      ? {
          style,
          formatter: () => {
            return (originVal * 100).toFixed(label.reserveDecimalCount) + '%'
          }
        }
      : false

    return {
      ...options,
      statistic: {
        title,
        content
      }
    }
  }

  protected configThreshold(chart: Chart, options: LiquidOptions): LiquidOptions {
    const senior = parseJson(chart.senior)
    if (senior?.threshold?.enable) {
      const { liquidThreshold } = senior?.threshold
      if (liquidThreshold) {
        const { paletteQualitative10: colors } = (options.theme as any).styleSheet
        const liquidStyle = () => {
          const thresholdArr = liquidThreshold.split(',')
          let index = 0
          thresholdArr.forEach((v, i) => {
            if (options.percent > parseFloat(v) / 100) {
              index = i + 1
            }
          })
          return {
            fill: colors[index % colors.length],
            stroke: colors[index % colors.length]
          }
        }
        return { ...options, liquidStyle }
      }
    }
    return options
  }

  setupDefaultOptions(chart: ChartObj): ChartObj {
    chart.customAttr.label = {
      ...chart.customAttr.label,
      fontSize: 12,
      show: true,
      labelFormatter: {
        type: 'percent',
        thousandSeparator: true,
        decimalCount: 2
      }
    }
    return chart
  }

  protected setupOptions(chart: Chart, options: LiquidOptions): LiquidOptions {
    return flow(
      this.configTheme,
      this.configMisc,
      this.configLabel,
      this.configThreshold
    )(chart, options)
  }
  constructor() {
    super('liquid', DEFAULT_LIQUID_DATA)
  }
}
