<script setup>
import AMapLoader from "@amap/amap-jsapi-loader";
import { computed, onMounted, ref, shallowRef, toRefs, watch } from "vue";
import { init, registerMap } from "echarts";
import {
  countAchievementByArea,
  countAchievementByCity,
  countAchievementByProvince,
  countDemandByArea,
  countDemandByCity,
  countDemandByProvince,
  countEnterpriseByArea,
  countEnterpriseByCity,
  countEnterpriseByProvince,
  countExpertByArea,
  countExpertByCity,
  countExpertByProvince,
} from "@/api/website/home";
import backBtnPng from "@/assets/images/map_back.png";
import RegionPagine from "@/views/website/home/comp/RegionPagine.vue";
import html2canvas from "html2canvas";
import anime from "animejs";
import { useI18n } from "vue-i18n";
import geoJSONRU from "@/assets/custom.geo.json";

const { t, locale } = useI18n();
const leftBoxPageNum = ref(1);
const rightBoxPageNum = ref(1);
const mapRef = ref(null);
const districtSearch = shallowRef(null);
const myEcharts = shallowRef(null);
const map = shallowRef(null);
const mapData = ref([]);
const props = defineProps({
  mapIndex: {
    type: Number,
    default: 0,
  },
});
const { mapIndex } = toRefs(props);
const emit = defineEmits(["changeMapIndex"]);
const methods = [
  {
    name: "expert",
    title: computed(() => t("map.expertMap")),
    byProvince: countExpertByProvince,
    byCity: countExpertByCity,
    byArea: countExpertByArea,
  },
  {
    name: "technology",
    // title: "技术分布地图",
    title: computed(() => t("map.technologyMap")),
    byProvince: countAchievementByProvince,
    byCity: countAchievementByCity,
    byArea: countAchievementByArea,
  },
  {
    name: "demand",
    // title: "需求分布地图",
    title: computed(() => t("map.demandMap")),
    byProvince: countDemandByProvince,
    byCity: countDemandByCity,
    byArea: countDemandByArea,
  },
  {
    name: "enterprise",
    // title: "企业分布地图",
    title: computed(() => t("map.enterpriseMap")),
    byProvince: countEnterpriseByProvince,
    byCity: countEnterpriseByCity,
    byArea: countEnterpriseByArea,
  },
];

const areaCount = ref([]); // 按行政区划统计
const industryCount = ref([]); // 按领域统计
const areaCountPaged = computed(() =>
  areaCount.value.slice(
    (leftBoxPageNum.value - 1) * 5,
    leftBoxPageNum.value * 5
  )
);
const industryCountPaged = computed(() =>
  industryCount.value.slice(
    (rightBoxPageNum.value - 1) * 5,
    rightBoxPageNum.value * 5
  )
);
const options = {
  // nameProperty: 'adcode',
  visualMap: {
    type: "piecewise",
    left: "center", //组件离容器左侧的距离,'left', 'center', 'right','20%'
    bottom: "30",
    orient: "horizontal", //图例排列方向
    padding: 5,
    pieces: [
      { gte: 0, lte: 99, label: "99", color: "#CAE9FD" },
      { gte: 100, lte: 299, label: "100-299", color: "#7ED2F7" },
      { gte: 300, lte: 499, label: "299-499", color: "#039DDD" },
      { gte: 500, label: "500", color: "#0D4884" },
    ],
    textStyle: {
      color: "#fff",
    },
    visibility: "off",
  },
  tooltip: {
    //提示框信息
    trigger: "item",
    formatter: "{b}\n{c}人",
  },
  series: [
    {
      type: "map",
      name: "中国",
      map: "map",
      data: [],
    },
  ],
};
const loadAMap = async () => {
  const AMap = await AMapLoader.load({
    key: "377d7c36dd385e2a722f29d4c6e1ffbf", // 申请好的Web端开发者Key，首次调用 load 时必填
    version: "2.0", // 指定要加载的 JS API 的版本，缺省时默认为 1.4.15
    plugins: [
      /*"AMap.DistrictSearch", "AMap.DistrictExplorer"*/
    ], // 需要使用的的插件列表，如比例尺'AMap.Scale'等
    AMapUI: {
      // 是否加载 AMapUI，缺省不加载
      version: "1.1", // AMapUI 缺省 1.1
      plugins: [], // 需要加载的 AMapUI ui插件
    },
  });
  map.value = new AMap.Map("container", {
    zoom: 4, //级别
    center: [108.946609, 34.262324], //中心点坐标
    // viewMode: '3D' //使用3D视图
  });
  map.value.on("click", mapClick);
  // districtSearch.value = new AMap.DistrictSearch({
  //   level: 'province',
  //   extensions: 'all',
  //   subdistrict: 1,
  //   showbiz: false,
  // })
};
const loading = ref(false);
const loadChinaDistrict = (adcode) => {
  loading.value = true;
  AMapUI.loadUI(["geo/DistrictExplorer"], (DistrictExplorer) => {
    const districtExplorer = new DistrictExplorer({
      map: map, //关联的地图实例
    });

    districtExplorer.loadAreaNode(adcode, async (error, areaNode) => {
      if (error) {
        console.error(error);
        loading.value = false;
        return;
      }
      const parentAdcode = areaNode.getAdcode();
      // 绘制载入的区划节点
      const geoJSON = {
        type: "FeatureCollection",
        features: areaNode.getSubFeatures(),
      };
      const level = getLevel(adcode);
      let result;
      try {
        if (level === 0) {
          result = await methods[mapIndex.value]["byProvince"]();
        } else if (level === 1) {
          result = await methods[mapIndex.value]["byCity"](adcode);
        } else if (level === 2) {
          result = await methods[mapIndex.value]["byArea"](adcode);
        }
      } catch (e) {
        loading.value = false;
        return;
      }
      if (result.industry)
        industryCount.value = Object.keys(result.industry).map((key) => ({
          name: key,
          count: result.industry[key],
        }));
      areaCount.value = result.count ?? [];
      mapData.value = geoJSON.features.map((el) => {
        const areaProp = el.properties;
        return {
          adcode: areaProp.adcode,
          name: areaProp.name,
          value:
            result.count.find((el) => el.code == areaProp.adcode)?.count ?? 0,
        };
      });

      registerMap("map", { geoJSON, specialAreas: {} });
      options.series[0].data = mapData.value;
      myEcharts.value.setOption(options);
      loading.value = false;
    });
  });
};

const loadRussiaDistrict = () => {
  registerMap("map", { geoJSON: geoJSONRU, specialAreas: {} });
  myEcharts.value.setOption(options);
  // TODO:get count
};
// 返回地图上一级
const backMap = () => {
  // loadChinaDistrict(parentAdcode)
  loadChinaDistrict("100000");
};

onMounted(async () => {
  await loadAMap();
  myEcharts.value = init(mapRef.value);
  myEcharts.value.on("click", mapClick);
  if (locale.value === "zh") {
    loadChinaDistrict("100000");
  } else {
    loadRussiaDistrict();
  }
});

/**
 * 根据adcode判断省市区级别
 * @param adcode
 * @return {number} 国家: 0 省: 1 市: 2 区: 3
 */
const getLevel = (adcode) => {
  adcode = adcode.toString();
  if (adcode === "100000") {
    return 0;
  }
  const splitPattern = /(\d{2})(\d{2})(\d{2})/;
  const resultArray = adcode.match(splitPattern).slice(1);
  // 国家: 0 省: 1 市: 2 区: 3
  let result = resultArray.indexOf("00");
  if (result === -1) {
    result = 3;
  }
  return result;
};
const mapClick = (ev) => {
  const level = getLevel(ev.data.adcode);
  if (level === 3) {
    return;
  }
  loadChinaDistrict(ev.data.adcode);
};

const playScrollAnimation = (direction, start) => {
  const pageWrap = document.querySelector(".page-wrap");
  const rootWrap = document.querySelector(".root-container");
  html2canvas(pageWrap).then((canvas) => {
    canvas.addEventListener("wheel", (ev) => {
      ev.stopPropagation();
      ev.preventDefault();
    });
    if (direction === "down") {
      rootWrap.insertBefore(canvas, pageWrap);
    } else if (direction === "up") {
      rootWrap.appendChild(canvas);
      rootWrap.style.transform = "translateY(-100%)";
    }
    anime({
      targets: rootWrap,
      translateY: direction === "down" ? "-100%" : "0",
      duration: 300,
      easing: "linear",
      begin: start,
      complete: () => {
        rootWrap.removeChild(canvas);
        rootWrap.style.transform = "translateY(0%)";
        isScrolling.value = false;
      },
    });
  });
};

const isScrolling = ref(false);
const handleScroll = async (ev) => {
  let direction = ev.deltaY > 0 ? "down" : "up";
  // 判断滚轮滚动方向
  if (
    (direction === "down" && mapIndex.value >= methods.length - 1) ||
    (direction === "up" && mapIndex.value <= 0)
  ) {
    return;
  }
  ev.preventDefault();
  ev.stopPropagation();
  if (isScrolling.value) {
    return;
  }
  isScrolling.value = true;
  playScrollAnimation(direction, () => {});
  if (direction === "down" && mapIndex.value < methods.length - 1) {
    emit("changeMapIndex", mapIndex.value + 1);
  } else if (direction === "up" && mapIndex.value > 0) {
    emit("changeMapIndex", mapIndex.value - 1);
  }
};

watch(mapIndex, (newVal, oldVal) => {
  console.log(`mapIndex change from ${oldVal} to ${newVal}`);
  if (newVal === oldVal) {
    return;
  }
  isScrolling.value = true;
  const direction = newVal > oldVal ? "down" : "up";
  playScrollAnimation(direction, () => {});
  if (locale.value === "zh") {
    loadChinaDistrict("100000");
  } else {
    loadRussiaDistrict();
  }
});

watch(locale, (newVal) => {
  console.log(newVal);
  if (newVal === "zh") {
    loadChinaDistrict("100000");
  } else if (newVal === "ru") {
    loadRussiaDistrict();
  }
});
</script>

<template>
  <div class="root-wrap">
    <div class="root-container">
      <div class="page-wrap" @wheel="handleScroll">
        <div class="title">{{ methods[mapIndex].title.value }}</div>
        <div v-if="loading" class="loading-modal"></div>
        <!--   返回上一级按钮   -->
        <div class="back-btn" @click="backMap">
          <img :src="backBtnPng" alt="back" />
        </div>
        <!--  人数表格  -->
        <div class="count-table area">
          <div class="table">
            <div class="head">
              <div class="th">
                <div class="title">地区</div>
                <div class="count">人数</div>
              </div>
            </div>
            <div class="body">
              <div v-for="item in areaCountPaged" :key="item.adcode" class="tr">
                <div class="title">{{ item.name }}</div>
                <div class="count">{{ item.count }}</div>
              </div>
            </div>
          </div>
          <RegionPagine
            v-model:page="leftBoxPageNum"
            :total="areaCount.length"
          />
        </div>
        <!--     领域   -->
        <div class="count-table industry">
          <div class="table">
            <div class="head">
              <div class="th">
                <div class="title">领域</div>
                <div class="count">人数</div>
              </div>
            </div>
            <div class="body">
              <div
                v-for="item in industryCountPaged"
                :key="item.adcode"
                class="tr"
              >
                <div class="title">{{ item.name }}</div>
                <div class="count">{{ item.count }}</div>
              </div>
            </div>
          </div>
          <RegionPagine
            v-model:page="rightBoxPageNum"
            :total="industryCount.length"
          />
        </div>
        <div id="map-container" ref="mapRef"></div>
        <div
          id="container"
          style="
            width: 100%;
            height: 100%;
            background-color: rgb(0, 0, 0);
            display: none;
          "
        ></div>
      </div>
    </div>
  </div>
</template>

<style lang="scss" scoped>
.scroll-to-top {
  animation: 1s linear infinite page-scroll;
}

.root-wrap {
  width: 100%;
  height: 100%;
  overflow: hidden;

  .root-container {
    width: 100%;
    height: 100%;

    > canvas {
      transition: all 0.3s linear;
    }

    .page-wrap {
      width: 100%;
      height: 100%;
      //top: 0;
      //left: 0;
      position: relative;
      //transition: all 0.3s linear;
      //animation: 1s linear forwards page-scroll;
      .loading-modal {
        position: absolute;
        left: 0;
        top: 0;
        background: #f0f2f5;
      }

      #map-container {
        width: 100%;
        height: 100%;
        background: linear-gradient(0deg, #010101, #041744);
      }

      > .title {
        position: absolute;
        top: 75px;
        width: 100%;
        text-align: center;
        font-size: 36px;
        font-family: Source Han Sans CN, sans-serif;
        font-weight: 300;
        color: #ffffff;
        z-index: 101;
      }

      .back-btn {
        position: absolute;
        left: 120px;
        top: 120px;
        z-index: 99;
        cursor: pointer;
      }

      .count-table {
        position: absolute;

        z-index: 101;

        &.area {
          top: 200px;
          left: 120px;
        }

        &.industry {
          top: 200px;
          right: 120px;
        }

        .table {
          border: 1px solid #0054ff;

          .head,
          .body {
            .tr,
            .th {
              display: flex;
              color: white;

              .title,
              .count {
                width: 100px;
                padding: 8px 12px;
                text-align: center;
              }

              .title {
                border-right: 1px solid #0054ff;
              }
            }

            .th {
              border-bottom: 1px solid #0054ff;
            }

            .tr {
              color: rgb(161, 192, 255);
            }
          }
        }

        .pagination {
          display: flex;
        }
      }
    }
  }
}

//@keyframes page-scroll {
//  0% {
//    transform: translateY(0);
//  }
//  100% {
//    transform: translateY(-100%);
//  }
//}
</style>
