import { useRef } from "react";
import portEntityBillboardImage from "~/assets/images/map_bi/point/dianwei.png";
import branchOfficeEntityBillboardImage from "~/assets/images/map_bi/point/gongsidianwei.png";
import edgeCMT from "./edge/cmt.js";
import edgeCSY from "./edge/csy.js";
import edgeCZKS from "./edge/czks.js";
import edgeQHD from "./edge/qhd.js";
import {
  addMergedEntityCollection,
  createEntityCollection,
  createId,
  getBillboard,
  getPosition,
  removeEntityCollection,
} from "./mapUtils";
import mitt from "./mitt";
import { changeCoverMaskVisibleMittKey } from "./mittKey";
import { chunkedLoad, filterNull, formatPolygon } from "./utils";
import "./TrajectoryPolylineTrailLinkMaterialProperty.js";
import "./WallPolylineTrailLinkMaterialProperty";

const portPoint = [
  {
    id: "00002",
    name: "沧州黄骅港矿石港务有限公司",
    introduce:
      "公司现共有10个泊位（10-20万吨级），设计年通过能力6400万吨。堆场面积176万平米，堆存能力740万吨，大型装卸设备44台套。",
    position: { x: 117.91412, y: 38.35902 },
    corpinfoId: "f8da1790b1034058ae2efefd69af3284",
  },
  {
    id: "00003",
    name: "秦皇岛港",
    introduce:
      "秦皇岛港分为东、西两个港区，现有生产性泊位50个，年设计通过能力2.26亿吨，经营货类主要包括煤炭、金属矿石、油品及液体化工、集装箱及其他杂货等。",
    position: { x: 119.61254, y: 39.92572 },
  },
  {
    id: "00004",
    name: "曹妃甸实业港务",
    introduce:
      "公司现共有6个泊位(5-30万吨级)，设计年通过能力6550万吨。堆场面积146万平米，堆存能力1350万吨，大型装卸设备23台套。",
    position: { x: 118.51022, y: 38.93503 },
    corpinfoId: "8854edee3aa94be496cee676b6d4845a",
  },
  {
    id: "00005",
    name: "曹妃甸煤炭港务",
    introduce:
      "公司现共有5个泊位（5-10万吨级），设计年通过能力5000万吨。堆场面积83万平米，堆存能力373.5万吨，大型装卸设备19台套。",
    position: { x: 118.43701, y: 38.9866 },
    corpinfoId: "6aa255d41602497fa0f934a822820df4",
  },
];

const Cesium = window.Cesium;

export default function useMapMethods(viewerRef, request) {
  // 获取当前 Cesium 实例：初始化前为空，地图方法会在 initMap 完成后被调用。
  const getViewer = () => viewerRef.current;

  // 默认中心点：初始化和回到首页视角时使用，保持全局港区俯视高度。
  const defineCenterPoint = {
    longitude: 119.6486945226887,
    latitude: 39.93555616569192,
    height: 900000,
  };

  // 当前中心点：记录最近一次 flyTo 的视角，供外部按钮回到当前位置。
  const currentCenterPointRef = useRef({
    longitude: 119.6486945226887,
    latitude: 39.93555616569192,
    height: 900000,
  });

  // 上一次中心点：从分公司返回港口层级时，需要回退到进入前的视角。
  const previousCenterPointRef = useRef({
    longitude: 119.6486945226887,
    latitude: 39.93555616569192,
    height: 900000,
  });

  // 设置中心点
  const flyTo = ({ longitude, latitude, height } = defineCenterPoint) => {
    getViewer().camera.flyTo({ destination: getPosition(longitude, latitude, height), duration: 2 });
    previousCenterPointRef.current = { ...currentCenterPointRef.current };
    currentCenterPointRef.current = { longitude, latitude, height };
  };

  // 返回当前中心点
  const returnCurrentCenterPoint = () => {
    const { longitude, latitude, height } = currentCenterPointRef.current;
    getViewer().camera.flyTo({ destination: getPosition(longitude, latitude, height), duration: 2 });
  };

  // 返回上一次中心点
  const returnPreviousCenterPoint = () => {
    const { longitude, latitude, height } = previousCenterPointRef.current;
    getViewer().camera.flyTo({ destination: getPosition(longitude, latitude, height), duration: 2 });
    currentCenterPointRef.current = { longitude, latitude, height };
  };

  // 切换场景模式
  const changeSceneMode = (type = "3d") => {
    getViewer().scene.mode = { "2d": Cesium.SceneMode.COLUMBUS_VIEW, "3d": Cesium.SceneMode.SCENE3D }[type];
  };

  // 添加港口点
  const addPortPoint = async () => {
    await chunkedLoad(portPoint, 10, async (item) => {
      const entityCollection = createEntityCollection("portEntityCollection");
      entityCollection.entities.add(
        new Cesium.Entity({
          id: item.id,
          name: item.name,
          position: getPosition(item.position.x, item.position.y),
          billboard: await getBillboard({ image: portEntityBillboardImage, name: item.name }),
          monitorItems: { data: { ...item, markType: "港口" } },
        }),
      );
      getViewer().dataSources.add(entityCollection);
    });
    await addMergedEntityCollection(getViewer(), "portEntityCollection");
  };

  // 移除港口点
  const removePortPoint = () => {
    removeEntityCollection(getViewer(), "portEntityCollectionMerged");
  };

  // 添加分公司点
  const addBranchOfficePoint = async (portArea = "", pointInfo = null) => {
    const { data = [] } = await request.getCorpInfoListAll({ eqPortArea: portArea, inType: [0, 1, 2, 6] });
    mitt.emit(changeCoverMaskVisibleMittKey, true);
    let branchOfficePoint = [];
    if (!pointInfo) {
      branchOfficePoint = filterNull(data);
    }
    else {
      branchOfficePoint = filterNull([pointInfo]);
    }
    await chunkedLoad(branchOfficePoint, 10, async (item) => {
      const entityCollection = createEntityCollection("branchOfficeEntityCollection");
      entityCollection.entities.add(
        new Cesium.Entity({
          id: item.id,
          name: item.corpName,
          position: getPosition(item.longitude, item.latitude),
          billboard: await getBillboard({ image: branchOfficeEntityBillboardImage, name: item.corpName }),
          monitorItems: {
            data: { ...item, id: item.id, markType: "分公司" },
          },
        }),
      );
      getViewer().dataSources.add(entityCollection);
    });
    await addMergedEntityCollection(getViewer(), "branchOfficeEntityCollection");
    mitt.emit(changeCoverMaskVisibleMittKey, false);
  };

  // 删除分公司点
  const removeBranchOfficePoint = () => {
    removeEntityCollection(getViewer(), "branchOfficeEntityCollectionMerged");
  };

  // 添加四色图
  const addFourColorDiagram = (id, corpionId) => {
    const edgeMap = {
      "00003": edgeQHD,
      "00002": edgeCZKS,
      "00005": edgeCMT,
      "00004": edgeCSY,
    };

    if (!edgeMap[id])
      return;
    mitt.emit(changeCoverMaskVisibleMittKey, true);
    const currentEdge = edgeMap[id]();
    const entityCollection = createEntityCollection(
      "fourColorDiagramEntityCollection",
    );
    // 先收集需要渲染的数据
    const itemsToRender = [];

    for (const currentEdgeKey in currentEdge) {
      const currentEdgeItem = currentEdge[currentEdgeKey];
      if (currentEdgeKey === "wallList")
        continue;

      for (let i = 0; i < currentEdgeItem.length; i++) {
        const item = currentEdgeItem[i];
        // 如果有 corpionId，则只添加匹配的；否则全部添加
        if (!corpionId || item.corpinfoId === corpionId) {
          itemsToRender.push(item);
        }
        if (!item.corpinfoId) {
          itemsToRender.push(item);
        }
      }
    }

    // 统一渲染
    itemsToRender.forEach((item) => {
      const latitudeAndLongitude = formatPolygon(item);
      entityCollection.entities.add(
        new Cesium.Entity({
          id: createId(),
          polygon: {
            hierarchy: Cesium.Cartesian3.fromDegreesArray(latitudeAndLongitude),
            extrudedHeight: item.stretchHeight,
            height: item.height,
            material: Cesium.Color.fromCssColorString(item.color),
            outline: !!item.strokeColor,
            outlineColor: Cesium.Color.fromCssColorString(item.strokeColor),
          },
        }),
      );
    });

    getViewer().dataSources.add(entityCollection);
    mitt.emit(changeCoverMaskVisibleMittKey, false);
  };

  // 删除四色图
  const removeFourColorDiagram = () => {
    removeEntityCollection(getViewer(), "fourColorDiagramEntityCollection");
  };

  // 添加墙
  const addWall = (id, corpionId) => {
    const edgeMap = {
      "00003": edgeQHD,
      "00002": edgeCZKS,
      "00005": edgeCMT,
      "00004": edgeCSY,
    };
    if (!edgeMap[id])
      return;
    mitt.emit(changeCoverMaskVisibleMittKey, true);
    const currentEdge = edgeMap[id]();
    const entityCollection = createEntityCollection("wallEntityCollection");
    const wallList = currentEdge.wallList;
    if (!Array.isArray(wallList))
      return;

    // 筛选需要渲染的边界墙
    const itemsToRender = wallList.filter(item => !corpionId || item.corpinfoId === corpionId);

    // 统一渲染
    itemsToRender.forEach((item) => {
      const latitudeAndLongitude = formatPolygon(item);
      const positions
        = Cesium.Cartesian3.fromDegreesArray(latitudeAndLongitude);
      const pointCount = latitudeAndLongitude.length / 2;

      entityCollection.entities.add(
        new Cesium.Entity({
          id: createId(),
          wall: {
            positions,
            material: new Cesium.WallPolylineTrailLinkMaterialProperty(getViewer()),
            maximumHeights: Array.from({ length: pointCount }).fill(40),
            minimumHeights: Array.from({ length: pointCount }).fill(0),
          },
        }),
      );
    });

    getViewer().dataSources.add(entityCollection);
    mitt.emit(changeCoverMaskVisibleMittKey, false);
  };

  // 删除墙
  const removeWall = () => {
    removeEntityCollection(getViewer(), "wallEntityCollection");
  };

  // 点位聚合
  const enabledClustering = (dataSource) => {
    dataSource.clustering.enabled = true; // 聚合开启
    dataSource.clustering.pixelRange = 50; // 设置像素范围，以扩展显示边框
    dataSource.clustering.minimumClusterSize = 5; // 设置最小的聚合点数目，超过此数目才能聚合
    let removeListener;
    // 按聚合层级创建对应图标
    const pinBuilder = new Cesium.PinBuilder();
    const pin100 = pinBuilder
      .fromText("100+", Cesium.Color.BLUE, 48)
      .toDataURL();
    const pin50 = pinBuilder.fromText("50+", Cesium.Color.BLUE, 48).toDataURL();
    const pin40 = pinBuilder.fromText("40+", Cesium.Color.RED, 48).toDataURL();
    const pin30 = pinBuilder.fromText("30+", Cesium.Color.RED, 48).toDataURL();
    const pin20 = pinBuilder.fromText("20+", Cesium.Color.RED, 48).toDataURL();
    const pin10 = pinBuilder.fromText("10+", Cesium.Color.RED, 48).toDataURL();
    // 10以内聚合图标
    const singleDigitPins = Array.from({ length: 8 });
    for (let i = 0; i < singleDigitPins.length; ++i) {
      singleDigitPins[i] = pinBuilder
        .fromText(`${i + 2}`, Cesium.Color.VIOLET, 48)
        .toDataURL();
    }
    customStyle();

    function customStyle() {
      if (Cesium.defined(removeListener)) {
        removeListener();
        removeListener = undefined;
      }
      else {
        removeListener = dataSource.clustering.clusterEvent.addEventListener(
          (clusteredEntities, cluster) => {
            cluster.label.show = false;
            cluster.billboard.show = true;
            cluster.billboard.id = cluster.label.id;
            cluster.billboard.verticalOrigin = Cesium.VerticalOrigin.BOTTOM;
            cluster.billboard.horizontalOrigin = Cesium.HorizontalOrigin.CENTER;
            cluster.billboard.heightReference
              = Cesium.HeightReference.CLAMP_TO_GROUND;
            cluster.billboard.disableDepthTestDistance
              = Number.POSITIVE_INFINITY;
            const thresholdMap = [
              { threshold: 100, image: pin100 },
              { threshold: 50, image: pin50 },
              { threshold: 40, image: pin40 },
              { threshold: 30, image: pin30 },
              { threshold: 20, image: pin20 },
              { threshold: 10, image: pin10 },
            ];
            const matched = thresholdMap.find(
              ({ threshold }) => clusteredEntities.length >= threshold,
            );
            cluster.billboard.image = matched
              ? matched.image
              : singleDigitPins[clusteredEntities.length - 2];
          },
        );
      }
      const pixelRange = dataSource.clustering.pixelRange;
      dataSource.clustering.pixelRange = 0;
      dataSource.clustering.pixelRange = pixelRange;
    }
  };

  /**
   * desc: 添加点位
   * @param {Array} pointList
   * @param options {Object: {markIcon, type, subLabel, titleKey}} 配置项
   * @param options.markIcon {String} 扎点图标
   * @param options.markType {String} 扎点类型
   * @param options.subLabel {String} 二级标题（用于弹窗标题）
   * @param options.titleKey {String} 标题键（用于从item中获取标题）
   * @param options.isShowModal {Boolean} 是否显示弹窗
   */
  const addMarkPoint = async (pointList, options) => {
    if (!options.markType)
      throw new Error("请传入markType（扎点类型）");
    if (!options.markIcon)
      throw new Error("请传入markIcon（扎点图标）");
    mitt.emit(changeCoverMaskVisibleMittKey, true);
    await chunkedLoad(filterNull(pointList), 10, async (item) => {
      const entityCollection = createEntityCollection(
        `markEntityCollection_${options.markType}`,
      );
      const name = item[options.titleKey] || "";
      entityCollection.entities.add(
        new Cesium.Entity({
          id: createId(),
          name,
          position: getPosition(item.longitude || item.lng, item.latitude || item.lat),
          billboard: await getBillboard({ image: options.markIcon, name }),
          monitorItems: {
            data: { ...item, markType: `标记点_${options.markType}`, title: options.subLabel, isShowModal: options.isShowModal ?? true },
          },
        }),
      );
      getViewer().dataSources.add(entityCollection);
    });
    const dataSource = await addMergedEntityCollection(
      getViewer(),
      "markEntityCollection",
      options.markType,
    );
    enabledClustering(dataSource);
    mitt.emit(changeCoverMaskVisibleMittKey, false);
  };

  // 删除点位
  const removeMarkPoint = (markType) => {
    removeEntityCollection(getViewer(), `markEntityCollectionMerged${markType ? `_${markType}` : ""}`);
  };

  return {
    flyTo,
    returnCurrentCenterPoint,
    returnPreviousCenterPoint,
    changeSceneMode,
    addPortPoint,
    removePortPoint,
    addBranchOfficePoint,
    removeBranchOfficePoint,
    addFourColorDiagram,
    removeFourColorDiagram,
    addWall,
    removeWall,
    addMarkPoint,
    removeMarkPoint,
  };
}
