import * as echarts from 'echarts';

const BAR_WIDTH = '20px';
const myChart: any = {};
let chartDom: any;
let winId = '';
const observeObj: any = {};

// 通用颜色配置
const commonEchartColor = {
  light: {
    // x轴文字颜色
    xAxisColor: '#333',
    // y轴文字颜色
    yAxisColor: '#333',
    // 分割线颜色
    splitLineColor: '#00000033',
    // 提示框背景色
    tooltipBgColor: '#fff',
    // 提示框文字颜色
    tooltipTextColor: '#333',
    // 提示框边框颜色
    tooltipBorderColor: 'rgba(51, 51, 51, 0.3)',
    // 图例文字颜色
    legendTextColor: '#333',
    // 小分割线的颜色
    minorSplitLineColor: '#ddd',
  },
  dark: {
    // x轴文字颜色
    xAxisColor: 'rgba(255, 255, 255, 0.9)',
    // y轴文字颜色
    yAxisColor: 'rgba(255, 255, 255, 0.9)',
    // 分割线颜色
    splitLineColor: 'rgba(255, 255, 255, 0.3)',
    // 提示框背景色
    tooltipBgColor: '#333',
    // 提示框边框颜色
    tooltipBorderColor: 'rgba(255, 255, 255, 0.2)',
    // 提示框文字颜色
    tooltipTextColor: 'rgba(255, 255, 255, 0.9)',
    // 图例文字颜色
    legendTextColor: 'rgba(255, 255, 255, 0.8)',
    minorSplitLineColor: 'rgba(255, 255, 255, 0.2)', // 小分割线的颜色
  },
};

export const setOption = (key: string, option: any) => {
  myChart[key]?.setOption(option);
};

export const disposeAllEcharts = () => {
  for (const key in myChart) {
    myChart[key]?.dispose();
  }
};
export const disposeEchartsByKey = (key: any) => {
  myChart[key]?.dispose();
};
// isDark： 当前是否为深色模式
export const initEcharts = (id: string, win: string, type: string, param: any, isDark?: any) => {
  chartDom = document.getElementById(id) as HTMLElement;
  myChart[id] = echarts.init(chartDom);

  if (type === 'barChart') {
    barChart(id, param, isDark);
  }
  if (type === 'pieChart') {
    pieChart(id, param, isDark);
  }
  if (type === 'lineChart') {
    lineChart(id, param, isDark);
  }
  if (type === 'scatterChart') {
    scatterChart(id, param, isDark);
  }
  if (win) {
    winId = win;
    observeObj[winId] = new ResizeObserver(() => {
      onResize(myChart[id]);
    });
    observeObj[winId].observe(document.getElementById(winId) as HTMLElement);
  }
};
const onResize = (chart: any) => {
  if (chart) {
    chart.resize();
  }
};
// X轴缩放的规则
const zoomRule = [
  {
    type: 'slider',
    show: true,
    xAxisIndex: [0],
    start: 0,
    end: 2,
    textStyle: {
      color: 'transparent',
    },
    moveHandleSize: 10,
    height: 15,
    bottom: 10,
    maxValueSpan: 14, // 窗口最多有15个柱子
    minValueSpan: 4, // 窗口最少也要有5个柱子
    filterMode: 'empty',
    realtime: true,
    zoomLock: false, // 允许缩放
    showDetail: false,
  },
  // {
  //   type: 'inside',
  //   xAxisIndex: [0],
  //   start: 0,
  //   end: 2,
  //   zoomOnMouseWheel: false, // 鼠标滚轮缩放
  //   moveOnMouseMove: true, // 鼠标拖动
  //   moveOnMouseWheel: false, // 按住Ctrl+滚轮移动
  // },
];
// 深层对象的合并
const deepMerge = (target: any, source: any) => {
  for (const key in source) {
    if (source[key] && typeof source[key] === 'object' && !Array.isArray(source[key])) {
      target[key] = target[key] || {};
      deepMerge(target[key], source[key]);
    } else {
      target[key] = source[key];
    }
  }
  return target;
};

export const unObserve = () => {
  if (observeObj[winId]) {
    const el = document.getElementById(winId) as HTMLElement;
    if (el) {
      observeObj[winId].unobserve(el);
    }
    delete observeObj[winId];
  }
};
const barChart = (
  id: string,
  { series, yAxis, xAxis, grid, title, legend, tooltip, dataZoom, color }: any,
  isDark: any
) => {
  const option: any = {
    title: {},
    tooltip: {
      trigger: 'axis',
      axisPointer: {
        type: 'shadow',
      },
      backgroundColor: commonEchartColor[isDark ? 'dark' : 'light'].tooltipBgColor,
      textStyle: {
        color: commonEchartColor[isDark ? 'dark' : 'light'].tooltipTextColor,
      },
      borderColor: commonEchartColor[isDark ? 'dark' : 'light'].tooltipBorderColor,
    },
    legend: {
      left: '250',
      top: '25',
      show: true,
      data: [],
      textStyle: {
        color: commonEchartColor[isDark ? 'dark' : 'light'].legendTextColor,
      },
    },
    grid: {
      top: '10%',
      bottom: '10%',
      left: '10%',
      right: '10%',
    },
    xAxis: [
      {
        type: 'category',
        axisTick: { show: false },
        data: [],
        axisLabel: {
          show: true,
          interval: 0, // 0：强制显示所有标签  'auto'：自动计算间隔，以防止重叠
          color: commonEchartColor[isDark ? 'dark' : 'light'].xAxisColor,
          width: 120, // 标签宽度
          ellipsis: '...', // 省略号
          overflow: 'truncate',
        },
      },
    ],
    yAxis: [
      {
        type: 'value',
        // minInterval: 1,
        axisLabel: {
          color: commonEchartColor[isDark ? 'dark' : 'light'].yAxisColor,
        },
        // 分割线颜色
        splitLine: {
          show: true,
          lineStyle: {
            color: commonEchartColor[isDark ? 'dark' : 'light'].splitLineColor,
          },
        },
        // y轴name配置的颜色
        nameTextStyle: {
          color: commonEchartColor[isDark ? 'dark' : 'light'].yAxisColor,
        },
      },
    ],
    series: [],
    dataZoom: [],
  };
  if (yAxis) {
    for (const key in yAxis) {
      option.yAxis[0][key] = yAxis[key];
    }
  }
  if (xAxis) {
    if (xAxis instanceof Array) {
      for (let index = 0; index < xAxis.length; index++) {
        for (const key in xAxis[index]) {
          option.xAxis[index][key] = xAxis[index][key];
        }
      }
    } else {
      for (const key in xAxis) {
        option.xAxis[0][key] = xAxis[key];
      }
    }
  }
  if (grid) {
    for (const key in grid) {
      option.grid[key] = grid[key];
    }
  }
  if (title) {
    for (const key in title) {
      option.title[key] = title[key];
    }
  }

  if (legend) {
    for (const key in legend) {
      option.legend[key] = legend[key];
    }
  }

  if (color) {
    option.color = color;
  }

  if (tooltip) {
    for (const key in tooltip) {
      option.tooltip[key] = tooltip[key];
    }
  }
  if (dataZoom) {
    // option.dataZoom = dataZoom.map((item: any) => {
    //   return item;
    // });
    option.dataZoom = zoomRule;
  }

  const len = series?.length ?? 0;
  option.series =
    series?.map((item: any) => {
      if (!Reflect.has(item, 'type')) {
        item.type = 'bar';
      }
      if (!Reflect.has(item, 'barMaxWidth')) {
        item.barMaxWidth = BAR_WIDTH;
      }
      // 1、柱子之间的距离
      item.barGap = '0';
      // 2、堆叠柱子宽度
      if (item.stack === 'total') {
        item.barMaxWidth = '40px';
      }
      // 3、多个并列柱子 增加背景颜色
      if (len > 1 && item.stack !== 'total') {
        item.showBackground = true;
        item.backgroundStyle = {
          color: 'rgba(180, 180, 180, 0.15)',
        };
      }
      return item;
    }) ?? [];
  if (option) {
    myChart[id].setOption(option);
  }

  myChart[id].on('click', (data: any) => {
    const param = {
      value: data.value,
      unit: data.seriesName,
      name: data.name,
    };

    sessionStorage.setItem('clickBarChart', JSON.stringify(param));
  });
};
const pieChart = (
  id: string,
  { series, color, title, tooltip, legend, grid }: any,
  isDark: any
) => {
  const option: any = {
    background: 'transparent',
    tooltip: {
      trigger: 'item',
      backgroundColor: commonEchartColor[isDark ? 'dark' : 'light'].tooltipBgColor,
      textStyle: {
        color: commonEchartColor[isDark ? 'dark' : 'light'].tooltipTextColor,
      },
      borderColor: commonEchartColor[isDark ? 'dark' : 'light'].tooltipBorderColor,
    },
    title: {},
    grid: {},
    legend: {
      top: '5%',
      left: 'center',
      show: true,
      borderWidth: 0,
      textStyle: {
        color: commonEchartColor[isDark ? 'dark' : 'light'].legendTextColor,
      },
    },
    series: [
      {
        name: '',
        type: 'pie',
        radius: ['40%', '70%'],
        avoidLabelOverlap: false,
        itemStyle: {
          borderRadius: 10,
          // borderColor: '#fff',
          borderWidth: 2,
        },
        label: {
          show: false,
          position: 'center',
        },
        emphasis: {
          label: {
            show: true,
            fontSize: 40,
            fontWeight: 'bold',
          },
        },
        labelLine: {
          show: false,
        },
        data: [],
      },
    ],
  };
  if (color) {
    option.color = color;
  }

  if (title) {
    for (const key in title) {
      option.title[key] = title[key];
    }
  }
  if (grid) {
    for (const key in grid) {
      option.grid[key] = grid[key];
    }
  }

  if (tooltip) {
    for (const key in tooltip) {
      option.tooltip[key] = tooltip[key];
    }
  }

  if (legend) {
    for (const key in legend) {
      option.legend[key] = legend[key];
    }
  }

  option.series =
    series.map((item: any) => {
      const seriesObj = {
        name: item.name,
        type: 'pie',
        radius: item.radius || ['40%', '70%'],
        center: item.center ? item.center : ['50%', '60%'],
        avoidLabelOverlap: false,
        itemStyle: item.itemStyle || {
          borderRadius: 5,
          borderColor: commonEchartColor[isDark ? 'dark' : 'light'].tooltipBgColor,
          borderWidth: 2,
        },
        label: item.label || {
          show: false,
          position: 'center',
        },
        emphasis: item.emphasis || {
          label: {
            show: true,
            fontSize: 40,
            fontWeight: 'bold',
          },
        },
        labelLine: item.labelLine || {
          show: false,
        },
        data: item.data,
      };
      if (!Reflect.has(item, 'type')) {
        seriesObj.type = 'pie';
      }
      return seriesObj;
    }) ?? [];
  if (option) {
    myChart[id].setOption(option);
  }
};
const lineChart = (
  id: string,
  { title, tooltip, legend, grid, xAxis, yAxis, series, color, dataZoom }: any,
  isDark: any
) => {
  const option: any = {
    title: {},
    tooltip: {
      trigger: 'axis',
      axisPointer: {
        type: 'line',
      },
      backgroundColor: commonEchartColor[isDark ? 'dark' : 'light'].tooltipBgColor,
      textStyle: {
        color: commonEchartColor[isDark ? 'dark' : 'light'].tooltipTextColor,
      },
      borderColor: commonEchartColor[isDark ? 'dark' : 'light'].tooltipBorderColor,
    },
    legend: {
      top: '5%',
      left: 'center',
      show: true,
      data: [],
      textStyle: {
        color: commonEchartColor[isDark ? 'dark' : 'light'].legendTextColor,
      },
    },
    grid: {
      top: '10%',
      bottom: '10%',
      left: '10%',
      right: '10%',
    },
    xAxis: [
      {
        type: 'category',
        boundaryGap: false,
        data: [],
        axisLabel: {
          show: true,
          interval: 0,
          color: commonEchartColor[isDark ? 'dark' : 'light'].xAxisColor,
        },
        // 分割线颜色
        splitLine: {
          show: false,
          lineStyle: {
            color: commonEchartColor[isDark ? 'dark' : 'light'].splitLineColor,
          },
        },
      },
    ],
    yAxis: [
      {
        type: 'value',
        minInterval: 1,
        axisLabel: {
          color: commonEchartColor[isDark ? 'dark' : 'light'].yAxisColor,
        },
        // 分割线颜色
        splitLine: {
          show: true,
          lineStyle: {
            color: commonEchartColor[isDark ? 'dark' : 'light'].splitLineColor,
          },
        },
        minorSplitLine: {
          lineStyle: {
            color: commonEchartColor[isDark ? 'dark' : 'light'].minorSplitLineColor,
          },
        },
      },
    ],
    series: [],
  };
  if (title) {
    for (const key in title) {
      option.title[key] = title[key];
    }
  }
  if (tooltip) {
    for (const key in tooltip) {
      option.tooltip[key] = tooltip[key];
    }
  }
  if (legend) {
    for (const key in legend) {
      option.legend[key] = legend[key];
    }
  }
  if (grid) {
    for (const key in grid) {
      option.grid[key] = grid[key];
    }
  }
  if (yAxis) {
    if (yAxis instanceof Array) {
      for (let index = 0; index < yAxis.length; index++) {
        option.yAxis[index] = deepMerge(option.yAxis[index], yAxis[index]);
      }
    } else {
      option.yAxis[0] = deepMerge(option.yAxis[0], yAxis);
    }
  }
  if (xAxis) {
    if (xAxis instanceof Array) {
      for (let index = 0; index < xAxis.length; index++) {
        option.xAxis[index] = deepMerge(option.xAxis[index], xAxis[index]);
      }
    } else {
      option.xAxis[0] = deepMerge(option.xAxis[0], xAxis);
    }
  }
  if (color) {
    option.color = color;
  }

  if (dataZoom) {
    // option.dataZoom = dataZoom.map((item: any) => {
    //   return item;
    // });
    option.dataZoom = zoomRule;
  }
  option.series =
    series.map((item: any) => {
      if (!Reflect.has(item, 'type')) {
        item.type = 'line';
      }
      return item;
    }) ?? [];
  if (option) {
    myChart[id].setOption(option);
  }
};

// 散点图，用的不多，还需要优化
const scatterChart = (id: string, { tooltip, xAxis, yAxis, series, dataset }: any, isDark: any) => {
  const option: any = {
    tooltip: {
      trigger: 'axis',
      axisPointer: {
        type: 'line',
      },
      backgroundColor: commonEchartColor[isDark ? 'dark' : 'light'].tooltipBgColor,
      textStyle: {
        color: commonEchartColor[isDark ? 'dark' : 'light'].tooltipTextColor,
      },
      borderColor: commonEchartColor[isDark ? 'dark' : 'light'].tooltipBorderColor,
    },
    xAxis: [
      {
        axisLabel: {
          show: true,
          color: commonEchartColor[isDark ? 'dark' : 'light'].xAxisColor,
        },
        axisLine: {
          lineStyle: {
            color: commonEchartColor[isDark ? 'dark' : 'light'].xAxisColor,
          },
        },
        // 分割线颜色
        splitLine: {
          show: true,
          lineStyle: {
            type: 'dashed',
            color: commonEchartColor[isDark ? 'dark' : 'light'].splitLineColor,
          },
        },
      },
    ],
    yAxis: {
      axisLabel: {
        color: commonEchartColor[isDark ? 'dark' : 'light'].yAxisColor,
      },
      name: '',
      // 分割线颜色
      splitLine: {
        show: true,
        lineStyle: {
          type: 'dashed',
          color: commonEchartColor[isDark ? 'dark' : 'light'].splitLineColor,
        },
      },
      axisLine: {
        lineStyle: {
          color: commonEchartColor[isDark ? 'dark' : 'light'].xAxisColor,
        },
      },
      nameTextStyle: {
        color: commonEchartColor[isDark ? 'dark' : 'light'].yAxisColor,
      },
    },
    series: [],
  };
  if (tooltip) {
    for (const key in tooltip) {
      option.tooltip[key] = tooltip[key];
    }
  }
  if (yAxis) {
    for (const key in yAxis) {
      option.yAxis[key] = yAxis[key];
    }
  }
  if (xAxis) {
    if (xAxis instanceof Array) {
      for (let index = 0; index < xAxis.length; index++) {
        for (const key in xAxis[index]) {
          option.xAxis[index][key] = xAxis[index][key];
        }
      }
    } else {
      for (const key in xAxis) {
        option.xAxis[0][key] = xAxis[key];
      }
    }
  }
  if (series) {
    option.series = series;
  }
  if (dataset) {
    option.dataset = dataset;
  }
  if (option) {
    myChart[id].setOption(option);
  }
};

export enum EColor {
  YELLOW = '#ffc72c',
  RED = '#f5878b',
  GRAY = '#888b9c',
}
