<script setup lang="ts">
import type { EChartsOption, SeriesOption } from 'echarts'
import type { LegendInfo } from '@/types/echarts/homeAnalysisChart'

import { ref, shallowRef, watch } from 'vue'
import { cloneDeep } from 'lodash'
import { nextTick } from 'vue'
import { debounceFunc } from '@/utils/common'
import echarts from './index'
import type { YAXisOption } from 'echarts/types/dist/shared'

interface Props {
  loading: boolean
  legend: Array<LegendInfo>
  data: Array<any>
  xAxisDataField: string // 用于标明x轴数据字段是来自数据中的哪个字段
}

const props = defineProps<Props>()

const MAX_INTERVAL = 5 // y轴最大间隔数

/**
 * @description: 格式化tooltip
 * @param {*} params 表格数据
 * @return {*}
 */
const formatterTooltip = (params: Object | Array<any>) => {
  if (Array.isArray(params)) {
    let circle = `<span style="display:inline-block;margin-right:5px;border-radius:50%;
    width:10px;height:10px;left:5px;background-color:`
    let result = `<span style="font-weight:bold;">${params[0].axisValueLabel}</span>`
    params.map((item, index) => {
      let data = `${circle}${props.legend[index].color}"></span>
    <span >
    <span  style="display: inline-block;  box-sizing: border-box;
  padding-right: 50px;">${props.legend[index].cnName}</span><span>${item['value']}<span>`
      result += `<br/>${data}`
    })
    return result
  } else {
    return `{b0}: {c0}<br />{b1}: {c1}`
  }
}

// 颜色
// const colorList = [
//   '#00e070',
//   '#1495eb',
//   '#993333', // Dark Red
//   '#FFD700', // Bright Yellow
//   '#FF00FF', // Magenta
//   '#FFA500', // Orange
//   '#800080', // Dark Purple
//   '#A52A2A', // Brown
//   '#FF4500', // Orange Red
//   '#FF6347', // Tomato
//   '#B22222', // Firebrick
//   '#FF1493', // Deep Pink
// ]

let baseOptions: EChartsOption = {
  grid: {
    left: '3%',
    right: '4%',
    bottom: '3%',
    containLabel: true,
  },
  xAxis: {
    type: 'category',

    axisLabel: {
      showMaxLabel: true,
    },
    axisTick: {
      alignWithLabel: true,
    },
  },
  yAxis: {
    type: 'value',
    minInterval: 1,
  },
  tooltip: {
    trigger: 'axis',
    formatter: (params: Object | Array<any>) => formatterTooltip(params),
  },
  series: [],
}

let baseSeries: SeriesOption = {
  symbol: 'circle',
  symbolSize: 5,
  showSymbol: false,
  // itemStyle要在lineStyle前面，这个item会把line的样式覆盖掉，并且必须要有line，不然也会被item替换掉
  itemStyle: {
    color: 'rgb(255,255,255)',
    borderColor: '#1495eb', // symbol边框颜色
    borderWidth: 2, // symbol边框宽度
  },
  lineStyle: {
    color: '#1495eb',
  },
  name: '',
  data: [],
  type: 'line',
  smooth: false,
}

// 图表dom对象
const chartRef = ref<HTMLElement>()

// 图表实例
const chartInstance = shallowRef<echarts.ECharts>()

// 图表尺寸变化的观察者
let chartSizeOb: ResizeObserver | null = null

/**
 * @description: 图表和图表实例是否都存在
 * @return {*}
 */
const isExistChart = (): boolean => {
  if (chartRef.value && chartInstance.value) return true
  return false
}

/**
 * @description: 更改图的加载状态
 * @param {*} newState
 * @return {*}
 */
const changeChartsLoading = (newState: boolean) => {
  if (!isExistChart()) return
  if (newState) chartInstance.value!.showLoading()
  else chartInstance.value!.hideLoading()
}

/**
 * @description: 更新图表大小
 * @return {*}
 */
const chartResize = () => {
  nextTick(() => {
    chartInstance.value?.resize()
  })
}

/**
 * @description: 初始化图表的信息
 * @return {*}
 */
const initChart = () => {
  if (!chartRef.value) return

  chartInstance.value = echarts.init(chartRef.value)
  // 只监听window会导致当侧边栏缩放时，dom大小变化但无法resize
  // 所以需要使用ovserver对整个dom进行监听
  const debounceResize = debounceFunc(chartResize, 300)
  chartSizeOb = new ResizeObserver(debounceResize)
  chartSizeOb.observe(chartRef.value!)
}

/**
 * @description: 创建Yaxis
 * @return {*}
 */
const createYAxis = (): Array<YAXisOption> => {
  let yAxis: Array<YAXisOption> = []

  props.legend.forEach(item => {
    yAxis.push({
      name: item.cnName,
      nameTextStyle: {
        fontWeight: 'bold',
      },
      alignTicks: true, // 开启轴线对齐
      type: 'value',
      minInterval: 1,
    })
  })
  return yAxis
}

/**
 * @description: 创建一条series数据
 * @return {*}
 */
const createSeries = (): SeriesOption[] => {
  let finalSeriesData: SeriesOption[] = []
  // 图例中包含了图例的name和颜色，那么根据这个name，
  // 去data中找到对应字段的值，形成一个series需要的data
  props.legend.forEach((item, index) => {
    let newSeries: SeriesOption = cloneDeep(baseSeries)
    let cData = cloneDeep(props.data)

    // 取出一个legend的里面的name，找到data中每条数据对应字段的值
    let newData = cData.map((data: any) => data[item.value])
    newSeries.name = item.value
    newSeries.data = newData
    newSeries.yAxisIndex = index
    newSeries.lineStyle!.color = item.color // 这里是线的颜色
    newSeries.itemStyle!.color = item.color
    finalSeriesData.push(newSeries)
  })

  return finalSeriesData
}

/**
 * @description: 创建xAxis的data
 * @return {*}
 */
const createXAxis = (): string[] => {
  if (props.data.length > 0) {
    let result: string[] = props.data.map(
      (item: any) => item[props.xAxisDataField],
    )

    return result
  }

  return []
}

/**
 * @description: 初始化选项
 * @return {*}
 */
const initOptions = () => {
  if (!isExistChart()) return
  chartInstance.value!.clear()
  if (props.data.length > 0) {
    let finalSeriesData = createSeries()
    let xAxisData = createXAxis()
    let yAxisData = createYAxis()

    baseOptions.series = finalSeriesData
    baseOptions.yAxis = yAxisData
    ;(baseOptions.xAxis as any).data = xAxisData
  } else {
    baseOptions = {
      title: {
        text: '暂无数据',
        textStyle: {
          fontSize: 16,
          fontWeight: 'normal',
        },
      },
    }
  }

  chartInstance.value!.setOption(baseOptions)
}

/**
 * @description: 观察loading状态，如果变为false证明加载完毕，需要重新设置一次数据
 * @return {*}
 */
watch(
  () => props.loading,
  (newState: boolean) => {
    changeChartsLoading(newState)
    if (newState === false) {
      if (!chartInstance.value) initChart()
      initOptions()
    }
  },
  { deep: true },
)

/**
 * @description: 当图例的信息变化的时候也需要重新设置选项
 * @return {*}
 */
watch(
  () => props.legend,
  () => {
    initOptions()
  },
  {
    deep: true,
  },
)
</script>

<template>
  <div class="chart" ref="chartRef" style="width: 100%; height: 365px"></div>
</template>

<style scoped></style>
