<script setup lang="ts">
import { Ref, defineProps, watchEffect } from "vue";
import type { EChartsOption } from "echarts";
import { useECharts } from "@/hooks/web/useECharts";
import { colorList, mergeOptions } from "@/components/chart/options/index";
import { registerMap } from "echarts";
import { isObject } from "@/utils/is";
import useEchartsAutoTooltip from "@/components/chart/logic/useEchartsAutoTooltip";
import {
  worddata,
  worldEnToCnNameMap,
  chinaLaLonData,
} from "@/assets/map/wordProvincialCapital";
const chartRef = ref<HTMLDivElement | null>(null);
const { setOptions, getInstance, echarts } = useECharts(
  chartRef as Ref<HTMLDivElement>
);
const yaTheme = localStorage.getItem("YA_THEME");

interface MapChartProps {
  title?: string;
  /**
   * 图表数据
   */
  chartData: any[];
  tooltipFormatter?:
    | string
    | ((params: any, ticket: any, callback: any) => string);
  /**
   * 是否需要手动设置一些其它的设置，需要结合otherOptions才能起作用
   */
  manual?: boolean;
  targetCoordinates: Array<any>;
  /**
   * 手动设置一些其它的设置，需要结合manual才能起作用
   */
  otherOptions?: EChartsOption;
  /**
   * 是否开启自动轮播
   */
  autotip?: boolean;
  makePoint?: boolean;
}

const {
  chartData = [],
  tooltipFormatter = "",
  manual = false,
  otherOptions = {},
  targetCoordinates = [],
} = defineProps<MapChartProps>();

const MAP_COLOR = {
  areaColor: yaTheme === "light" ? "#EEEEEE" : "#346E9A",
  borderColor: yaTheme === "light" ? "rgba(38,73,106,0.65)" : "#4A9DD7",
  shadowColor: "transparent",
  labelColor: "transparent",
  emphasisLabelColor: "transparent",
  emphasisAreaColor: "#45BCCA",
  emphasisBorderColor: "#FFFFFF",
};

const processLng = (lng) => {
  if (lng > -30) {
    lng = lng - 180;
  } else {
    lng = lng + 180;
  }
  return lng;
};

function processCoordinates(coords) {
  const [lng, lat] = coords;
  return [processLng(lng), lat];
}

let options: EChartsOption = {
  tooltip: {
    show: false,
    trigger: "item",
    position: "inside",
    confine: true,
    backgroundColor: "transparent",
    extraCssText:
      "z-index: 9;border-radius: 0; border: 0;padding: 0;background: red;margin: 0;min-width: 0;height: 0;",
    formatter: unref(tooltipFormatter) as any,
  },

  grid: {
    left: 0,
    right: 0,
    bottom: 0,
    top: 0,
  },
  geo: {
    map: "World",
    aspectScale: 1,
    roam: false,
    zoom: 1.2,
    itemStyle: {
      areaColor: MAP_COLOR.areaColor,
      borderColor: MAP_COLOR.borderColor,
      shadowColor: MAP_COLOR.shadowColor,
      shadowOffsetX: 0,
      shadowOffsetY: 10,
      shadowBlur: 1,
    },
    nameMap: worldEnToCnNameMap,
  },

  series: [
    {
      type: "map",
      map: "World",
      geoIndex: 1,
      aspectScale: 1,
      zoom: 1.2,
      labelLayout(params) {
        return {
          x: params.rect.x + params.rect.width / 2,
          y: params.rect.y + params.rect.height / 2,
          verticalAlign: "middle",
          align: "center",
        };
      },
      label: {
        show: false,
        color: MAP_COLOR.labelColor,
        fontSize: 10,
        lineHeight: 15,
        rich: {},
      },

      itemStyle: {
        areaColor: MAP_COLOR.areaColor,
        borderColor: MAP_COLOR.borderColor,
        shadowColor: MAP_COLOR.shadowColor,
      },

      emphasis: {
        disabled: true,
        itemStyle: {
          areaColor: MAP_COLOR.emphasisAreaColor,
          borderColor: MAP_COLOR.emphasisBorderColor,
          shadowColor: MAP_COLOR.shadowColor,
        },
        label: {
          show: false,
          color: MAP_COLOR.emphasisLabelColor,
        },
      },

      select: {
        disabled: true,
        itemStyle: {
          areaColor: MAP_COLOR.emphasisAreaColor,
          borderColor: MAP_COLOR.emphasisBorderColor,
          shadowColor: MAP_COLOR.shadowColor,
        },
        label: {
          color: MAP_COLOR.emphasisLabelColor,
        },
      },

      nameMap: worldEnToCnNameMap,

      data: [],
    },

    {
      type: "scatter",
      coordinateSystem: "geo",
      symbol:
        "image://data:image/png;base64,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",
      symbolSize: [45, 45],
      zlevel: 5,
      data: [
        { name: "目标", value: processCoordinates(unref(targetCoordinates)) },
      ],
    },

    {
      type: "effectScatter",
      coordinateSystem: "geo",
      symbolSize: 8,
      rippleEffect: {
        color: "rgba(217, 8, 8, 1)",
        brushType: "stroke",
      },
      itemStyle: {
        color: "rgba(217, 8, 8, 1)",
      },
      data: [],
    },

    {
      type: "lines",
      coordinateSystem: "geo",
      zlevel: 4,
      tooltip: {
        show: true,
        trigger: "item",
        position: "inside",
        confine: true,
        backgroundColor: "transparent",
        extraCssText:
          "z-index: 9;border-radius: 0; border: 0;padding: 0;background: red;margin: 0;min-width: 0;height: 0;",
        formatter: unref(tooltipFormatter) as any,
      },
      effect: {
        show: true,
        symbol: "pin",
        color: "#FF0A03",
        symbolSize: [3, 10],
      },
      lineStyle: {
        color: "rgba(255, 255, 255, 0.31)",
        width: 2,
        curveness: 0.2,
      },
      data: [],
    },
  ],
};

const getSeriesData = (chartData = []) => {
  const series = options.series || ([] as any);
  const mapData = [] as any;
  const effectScatter = [] as any;
  const linesData = [] as any;
  const findMapIndex = series.findIndex((item) => item.type === "map");
  const findEffectScatterIndex = series.findIndex(
    (item) => item.type === "effectScatter"
  );
  const findLinesIndex = series.findIndex((item) => item.type === "lines");
  chartData.map((item) => {
    const _item = item;
    mapData.push({
      name: item.state,
      value: 0,
      itemStyle: {
        areaColor: MAP_COLOR.emphasisAreaColor,
      },
    });

    var arr = []; //定义数组
    for (var i in chinaLaLonData) {
      arr.push({
        name: i,
        coordinate: chinaLaLonData[i],
      });
    }
    const isChina = item.state === "中国";
    const stateLat = worddata.find(
      (item) => item.name === _item.state
    )?.coordinate;
    let currentLocationLatlng = isChina
      ? chinaLaLonData[item.attackProvince]
      : stateLat;

    if (currentLocationLatlng && currentLocationLatlng.length) {
      effectScatter.push(processCoordinates(currentLocationLatlng));
      const newLinesItem = {
        coords: [
          processCoordinates(currentLocationLatlng),
          processCoordinates(unref(targetCoordinates)),
        ],
        ...item,
      };
      linesData.push(newLinesItem);
    }
  });
  series[findMapIndex].data = mapData;
  series[findEffectScatterIndex].data = effectScatter;
  series[findLinesIndex].data = linesData;
  return series;
};

const initChart = async () => {
  const worldMap = (await (
    await import("@/assets/map/worldCn.json")
  ).default) as any;
  registerMap("World", worldMap);
  // @ts-ignore
  options.tooltip!.formatter = unref(tooltipFormatter);
  options.series = getSeriesData(unref(chartData));
  // 如果是手动设置模式的话
  if (unref(manual) && isObject(unref(otherOptions))) {
    options = mergeOptions(options, unref(otherOptions));
  }
  setOptions(options);
};

watchEffect(() => {
  if (unref(chartData).length === 0) return;
  initChart();
});

onMounted(() => {
  initChart();
});
</script>

<template>
  <div
    class="chart"
    ref="chartRef"
    :style="{ width: '100%', height: '100%' }"
  ></div>
</template>

<style lang="scss">
.light-map-tip-box {
  min-width: 155px;
  padding: 12px 16px;
  box-sizing: border-box;
  background: rgba(255, 255, 255, 0.96);
  box-shadow: 0px 0px 8px 0px rgba(0, 0, 0, 0.2);
  border-radius: 4px;
  display: flex;
  flex-direction: column;
}

.light-map-tip-box-name {
  font-size: 12px;
  font-weight: 600;
  color: rgba(0, 0, 0, 0.65);
}

.light-map-tip-box-content {
  width: 100%;
  display: flex;
  flex-direction: column;
}

.light-map-tip-box-item {
  display: flex;
  align-items: center;
  font-size: 12px;
  justify-content: space-between;
  width: 100%;

  .light-map-tip-box-item-label {
    font-size: 12px;
    font-weight: 400;
    color: rgba(0, 0, 0, 0.65);
  }

  .light-map-tip-box-value {
    font-size: 12px;
    color: rgba(0, 0, 0, 0.4);
  }
}

.light-map-tip-box-item.mt-12 {
  margin-top: 12px;
}
</style>
