const chartYOptinos = ref([]) as Ref<any[]>;
const chartSeries = ref([]) as Ref<any[]>;

// 获取曲线数据
const { data, run, loading } = useRequest(loadChartData, {
  manual: true,
  onSuccess: async (res) => {
    if (!res) return { title: { text: null } } as any as Options;
    const _yoptions = deepClone(res?.yoptions);
    const _series = deepClone(res?.series);

    const { yoptions, series } = await getYoptionsSeries(_yoptions, _series);
    chartYOptinos.value = yoptions;
    chartSeries.value = series;
  },
});

const options = computed(() => {
  const xMaxMin = data.value?.series && getYaxisMaxMin(data.value?.series, 0);

  return {
    chart: {
      zoomType: "x",
      spacingRight: isDeepSensor.value ? 220 : 10,
    },
    title: {
      text: null,
    },
    xAxis: {
      ...data.value?.xoptions,
      type: data.value?.xoptions?.type || "datetime", //X轴为日期时间类型
      tickPixelInterval: 140, //X轴标签间隔
      endOnTick: true,
      showFirstLabel: true,
      showLastLabel: true,
      startOnTick: false,
      minorGridLineColor: "#197F07",
      lineColor: "#197F07", //设置X轴颜色
      lineWidth: 2,
      crosshair: true,
      min: xMaxMin?.min,
      max: xMaxMin?.max,
      gridLineWidth: 1,
      events: {
        setExtremes: function (e: any) {
          //@ts-ignore
          let thisChart = this.chart;
          if (e.trigger !== "syncExtremes") {
            // Prevent feedback loop
            Highcharts.each(Highcharts.charts, function (chart) {
              if (chart !== thisChart) {
                if (chart?.xAxis?.[0].setExtremes) {
                  // It is null while updating
                  chart.xAxis[0].setExtremes(e.min, e.max, undefined, false, {
                    trigger: "syncExtremes",
                  });
                }
              }
            });
          }
        },
      },
      plotLines: [
        {
          color: "red", //线的颜色，定义为红色
          width: 2,
          label: {
            text: "",
            align: "left",
            x: 10,
            y: 10,
          },
          dashStyle: "LongDashDot", //默认值，这里定义为实线
          value:
            data.value?.series[0].data[data.value?.series[0].data.length - 1] &&
            data.value?.series[0].data[
              data.value?.series[0].data.length - 1
            ][0],
        },
      ],
      labels: {
        formatter: function () {
          //@ts-ignore
          if (this.chart?.xAxis[0]?.userOptions?.type == "datetime")
            //@ts-ignore
            return Highcharts.dateFormat(
              "%Y-%m-%d<br>%H:%M",
              this.value as number
            );
          //@ts-ignore
          return this.value.toFixed(
            this.chart?.xAxis[0]?.userOptions?.scale || 2
          );
        },
      },
    },
    yAxis: chartYOptinos.value,
    time: {
      useUTC: false,
    },
    plotOptions: {
      series: {
        turboThreshold: 0,
        allowPointSelect: false,
        dataLabels: {
          enabled: true,
          formatter: function () {
            //@ts-ignore
            const series = this.series;
            const yOption = data.value?.yoptions.find(
              (item) => item.title == series.name
            );
            const unit = series.userOptions.unit ?? "";
            const xType = series.chart.xAxis[0].userOptions.type;
            //@ts-ignore
            const x = this.x as number;
            //@ts-ignore
            const y = this.y as number;
            if (
              x == series.data[series.data.length - 1].x &&
              xType === "datetime"
            ) {
              //@ts-ignore
              return (
                Highcharts.dateFormat("%m-%d %H:%M:%S", x) +
                "<br>" +
                y.toFixed(series.userOptions.scale || data.value?.scale) +
                unit
              );
            }
          },
        },
        cursor: "pointer",
        events: {
          click: function (e) {
            if (config.value.sensorHasDeep) {
              // show deep sensor modal
              openDeepSensorModal(true, {
                sensorInnerCode: data.value?.sensorInnerCode,
                deep: e.point.y,
                title: `${sensorChartDesc.value?.sensorCode}(${sensorChartDesc.value?.siteCode}) 深度： ${e.point.y}m`,
              });
            }
          },
        },
      },
    },
    legend: legend.value,
    boost: {
      useGPUTranslations: false,
    },
    tooltip: {
      formatter: function () {
        //@ts-ignore
        const series = this.series;
        const yOption = data.value?.yoptions.find(
          (item) => item.title == series.name
        );
        const unit = series.userOptions.unit ?? "";
        //@ts-ignore
        const x = this.x as number;
        //@ts-ignore
        const y = this.y as number;
        if (series.chart.xAxis[0].userOptions.type == "linear") {
          return (
            "<strong>" +
            series.name +
            "</strong><br/>" +
            series.chart.yAxis[0].userOptions.title.text +
            ":" +
            y?.toFixed(series.userOptions.scale || data.value?.scale) +
            "<br/>" +
            series.chart.xAxis[0].userOptions.title?.text +
            ":" +
            x?.toFixed(series.userOptions.scale || data.value?.scale) +
            unit
          );
        }
        return (
          "<strong>" +
          series.name +
          "</strong>" +
          Highcharts.dateFormat("%Y-%m-%d %H:%M:%S", x) +
          ": " +
          y.toFixed(series.userOptions.scale || data.value?.scale) +
          unit
        );
      },
    },
    //   series: res?.series,
    series: getFitData(chartSeries.value),
  } as unknown as Options;
});

const getYoptionsSeries = async (yoptions, series) => {
  let _yoptions = yoptions;
  let _series = series;
  const newYoptions = _yoptions.map((item, index) => {
    //@ts-ignore
    const maxMin = getYaxisMaxMin(
      series.filter((serie) => serie.yAxis == item.id)
    );
    const max = index == 0 ? (item.max ? item.max : undefined) : undefined;
    const lineColor = index == 0 ? "#197F07" : undefined;
    const lineWidth = index == 0 ? 2 : undefined;
    //
    return {
      ...item,
      lineColor,
      lineWidth,
      smooth: true,
      title: {
        text: item.title,
        ...item.title,
      },
      labels: {
        formatter: function () {
          //@ts-ignore
          return this.value.toFixed(item.scale);
        },
      },

      max,
      min:
        item.min ?? item.plotLines?.[0].value
          ? Math.min(item.plotLines?.[0].value, maxMin.min)
          : maxMin.min,
    };
  });
  return { yoptions: newYoptions, series: _series };
};

const getStandarInterval = (t: number) => {
  if (t <= 0.1) {
    t = 0.1;
  } else if (t <= 0.2) {
    t = 0.2;
  } else if (t <= 0.25) {
    t = 0.25;
  } else if (t <= 0.4) {
    t = 0.4;
  } else if (t <= 0.5) {
    t = 0.5;
  } else if (t <= 0.6) {
    t = 0.6;
  } else {
    t = 1;
  }
  return t;
};

/**
 * @param min 数据最小值
 * @param max 数据最大值
 * @param tickInterval 刻度区间
 */
const calcR = (
  min: number,
  max: number,
  tickInterval: number
): [number, number, number] => {
  let tempmin = 0;
  if (min < 0) {
    while (tempmin > min) {
      tempmin -= tickInterval;
    }
  } else {
    while (tempmin + tickInterval < min) {
      tempmin += tickInterval;
    }
  }
  min = tempmin;
  let tickCount = 1;
  while (tickCount * tickInterval + min < max) {
    tickCount++;
  }
  max = tickCount * tickInterval + min;
  return [min, max, tickCount];
};

/**
 * 获取符合bizcharts内置逻辑的最大值最小值分布
 * @param list 数据列表
 * @param tickCount 最大刻度数 default  3
 * @param startWith0 最大值或者最小值是否从零开始 default false
 * @returns [min: number, max: number, tickCount: number]
 */
function standardRange(
  list: number[],
  tickCount = 6,
  startWith0 = false
): [number, number, number] {
  list = list.map((i) => (isNaN(Number(i)) ? 0 : Number(i)));

  const log10 = (n: number) => Math.log(n) / Math.log(10);
  let max = Math.max(...list);
  let min = Math.min(...list);
  // 数据全部分布在x轴同一侧，而且需要从零开始计算
  if (startWith0 && min * max >= 0) {
    min = min > 0 ? 0 : min;
    max = max < 0 ? 0 : max;
  }
  if (max === min) {
    const t = Math.abs(min);
    const mag = t == 0 ? 1 : Math.pow(10, Math.floor(log10(t)));
    return calcR(min, max, mag);
  }

  // 刻度区间长度，和长度数量级
  let tickInterval: number, mag: number;
  const rawTickInterval: number = (max - min) / tickCount;
  // 计算数量级
  mag = Math.pow(10, Math.floor(log10(rawTickInterval)));
  if (mag == rawTickInterval) {
    mag = rawTickInterval;
  } else {
    mag = mag * 10;
  }
  tickInterval = rawTickInterval / mag;

  //选取规范步长
  const stepLen = getStandarInterval(tickInterval);
  tickInterval = stepLen * mag;

  let res = calcR(min, max, tickInterval);

  if (res[2] > tickCount) {
    // 如果最后计算得出的刻度数大于计算值，步长扩大一级
    tickInterval = getStandarInterval(stepLen + 0.1) * mag;
    res = calcR(min, max, tickInterval);
  }
  return res;
}
/**
 * @param series 坐标轴对应的系列数据集合
 */
const getYaxisMaxMin = (data: Series[], index = 1) => {
  let list = [] as any[];
  // find series data list
  data.forEach((item) => {
    list.push(...item.data.map((i) => i[index]));
  });
  const [min, max] = standardRange(list);
  return { min, max };
};

interface Series {
  data: Array<[number | string, number | null]>;
  name: string;
  unit?: string;
  scale?: number;
  yAxis: string;
  type?: "column" | "spline";
}
