import { ref, watch, markRaw } from "vue";

export default function useRefrigerantTemp() {
  const deviceList = ref([]);
  const dataVizExtension = ref(null);

  const getBasicData = (viewer, dataVizExtn, deviceArr) => {
    dataVizExtension.value = markRaw(dataVizExtn);
    const devices = deviceArr.map((d) => ({
      ...d,
      id: d.device_number, // An ID to identify this device
      roomDbId: Number(d.room_dbid),
      position: JSON.parse(d.device_coordinate_3d), // World coordinates of this device
      sensorTypes: ["temperature"], // The types/properties this device exposes
      temp: 10,
      dbId: d.forge_dbid,
    }));
    deviceList.value = devices;
    initHeatMap(viewer, dataVizExtn, devices);
  };

  const initHeatMap = async (viewer, dataVizExtn, deviceList) => {
    const {
      SurfaceShadingData,
      SurfaceShadingPoint,
      SurfaceShadingNode,
      SurfaceShadingGroup,
    } = Autodesk.DataVisualization.Core;
    const shadingGroup = new SurfaceShadingGroup("iot-heatmap");
    const rooms = new Map();

    for (const { id, roomDbId, position, sensorTypes } of deviceList) {
      if (!id || roomDbId == -1) {
        continue;
      }

      if (!rooms.has(roomDbId)) {
        const room = new SurfaceShadingNode(id, roomDbId);
        shadingGroup.addChild(room);
        rooms.set(roomDbId, room);
      }
      const room = rooms.get(roomDbId);
      room.addPoint(new SurfaceShadingPoint(id, position, sensorTypes));
    }

    const shadingData = new SurfaceShadingData();
    shadingData.addChild(shadingGroup);
    shadingData.initialize(viewer.model);

    await dataVizExtn.setupSurfaceShading(viewer.model, shadingData);
    dataVizExtn.registerSurfaceShadingColors(
      "temperature",
      [0x0000ff, 0x00ff00, 0xffff00, 0xff0000]
    );
    dataVizExtn.renderSurfaceShading(
      "iot-heatmap",
      "temperature",
      getSensorValue
    );
  };

  // Function that provides sensor value in the range of [0.0, 1.0]
  function getSensorValue(device, sensorType, pointData) {
    const dev = deviceList.value.find(
      ({ device_number }) => device_number === device.id
    );
    console.log(9, device, dev);

    return (dev?.temp || 0) / 40;
  }

  function updateTemp() {
    console.log(8, deviceList.value, dataVizExtension.value.updateSurfaceShading);
    dataVizExtension.value.updateSurfaceShading(getSensorValue);
    

  }

  const transformDeviceNumber = (device_number) => {
    return device_number.replaceAll("_", "/");
  };

  const subscribeDevice = (deviceList) => {
    deviceList.forEach((d) => {
      const ordPath = transformDeviceNumber(d.device_number);
      getRealTempByBaja(ordPath);
    });
  };

  const getRealTempByBaja = (ordPath) => {
    window.require &&
      window.requirejs(["baja!"], (baja) => {
        console.log("進入 bajaSubscriber 準備執行BQL訂閱");
        const sub = new baja.Subscriber();
        function changeDeviceValue(temp) {
          const device = deviceList.value.find(
            ({ device_number }) =>
              transformDeviceNumber(device_number) === ordPath
          );
          console.log(7, device, temp);
          device.temp = Number(temp.replace(" °C", ""));
          updateTemp();
        }
        sub.attach("changed", (prop) => {
          if (prop && prop.$displayName === "Out") {
            console.log(5, ordPath, prop);
            if (prop.$getValue().getValueDisplay().includes(" °C")) {
              changeDeviceValue(prop.$getValue().getValueDisplay());
            }
          }
        });
        sub.attach("subscribed", (prop) => {
          if (prop && prop.$displayName === "Out") {
            console.log(6, ordPath, prop);
            if (prop.$getValue().getValueDisplay().includes(" °C")) {
              changeDeviceValue(prop.$getValue().getValueDisplay());
            }
          }
        });
        // ord 為要訂閱的點位
        // ord 為要訂閱的點位
        baja.Ord.make(`local:|foxs:|station:|slot:/${ordPath}`)
          .get()
          .then((folder) => {
            folder
              .getSlots()
              .is("control:NumericWritable")
              .eachValue((point) => {
                if (
                  point.getDisplayName() === "Temp" ||
                  point.getDisplayName() === "TEMP"
                ) {
                  baja.Ord.make(
                    `local:|foxs:|station:|slot:/${ordPath}/${point.getDisplayName()}`
                  ).get({ subscriber: sub });
                }
              });
          });
      });
  };

  watch(deviceList, (newValue) => {
    subscribeDevice(newValue);
  });

  return {
    getBasicData,
    updateTemp,
  };
}
