<template>
  <div class="index-page" @wheel="handleWheel">
    <div class="index-page-container" :class="!isFullScreen ? 'is-full-screen ' : ''">
      <div
        class="affix-container"
        id="indexpage-container"
        :style="{
          cursor: isDrag ? 'pointer' : 'default',
          transformOrigin: '0 0',
          transform: `scale(${isSizeRadio})`,
          height: imgBgObj.height + 'px',
          width: isFull ? '100%' : imgBgObj.width + 'px'
        }"
      >
        <div
          :class="isDrag ? 'indexpage-container-active' : 'indexpage-container'"
          v-if="imgBgObj.imgUrl"
          v-drag="isDrag"
          :style="{ scale: 1, transformOrigin: '0 0' }"
          ref="draggableElement"
        >
          <div class="indexpage-container-box">
            <img :src="imgBgObj.imgUrl" class="indexpage-container-box-img" />
            <div class="indexpage-container-box-point">
              <!-- 连线 -->
              <div v-if="legendObj.driveLineShow">
                <div class="line-box">
                  <svg id="svg" :width="imgBgObj.width" :height="imgBgObj.height">
                    <template v-for="(item, index) in state.mapRouteList" :key="index">
                      <!-- 定义箭头 -->
                      <defs>
                        <marker
                          id="forward-arrow"
                          viewBox="0 0 10 10"
                          refX="10"
                          refY="5"
                          orient="auto"
                          markerWidth="2"
                          markerHeight="2"
                        >
                          <path d="M 0 0 L 10 5 L 0 10 z" fill="black" />
                        </marker>
                        <!-- 反向箭头 -->
                        <marker
                          id="backward-arrow"
                          viewBox="0 0 10 10"
                          refX="0"
                          refY="5"
                          orient="auto"
                          markerWidth="2"
                          markerHeight="2"
                        >
                          <path d="M 10 0 L 0 5 L 10 10 z" fill="black" />
                        </marker>
                      </defs>
                      <template v-if="item.method == 0">
                        <line
                          :x1="Number(item.startPointX) * radio"
                          :y1="Number(item.startPointY) * radio"
                          :x2="Number(item.endPointX) * radio"
                          :y2="Number(item.endPointY) * radio"
                          :stroke="item.isSelect ? '#f48924' : '#00329F'"
                          :stroke-width="4 * radio"
                          :marker-start="item.direction === 2 ? 'url(#double-arrow-start)' : ''"
                          marker-end="url(#single-arrow)"
                          @click="handleChooseRoute(item, index)"
                        />
                        <path
                          :d="getLineMidArrowPath(item)"
                          stroke="none"
                          fill="black"
                          :stroke-width="4 * radio"
                          :marker-start="item.direction === 2 ? 'url(#backward-arrow)' : ''"
                          :marker-end="
                            item.direction === 2 ? 'url(#forward-arrow)' : 'url(#forward-arrow)'
                          "
                        />
                      </template>
                      <template v-else>
                        <path
                          :d="getCurvePath(item)"
                          :stroke="item.isSelect ? '#f48924' : '#00329F'"
                          :stroke-width="4 * radio"
                          fill="none"
                          :marker-start="item.direction === 2 ? 'url(#backward-arrow)' : ''"
                          :marker-end="
                            item.direction === 2 ? 'url(#forward-arrow)' : 'url(#forward-arrow)'
                          "
                          @click="handleChooseRoute(item, index)"
                        />
                      </template>
                    </template>
                  </svg>
                </div>
              </div>
              <!-- 小车 -->
              <div
                v-for="(item, index) in testCarList"
                :key="index"
                @dblclick="carDbClick(item, index)"
              >
                <div
                  class="indexpage-car-item"
                  v-if="legendObj.carShow"
                  :style="{
                    left: item.realX * radio + 'px',
                    top: item.realY * radio + 'px',
                    width: (carWidth / imgBgObj.resolution / 100) * radio + 'px',
                    height: (carHeight / imgBgObj.resolution / 100) * radio + 'px',
                    transform: 'rotate(' + radianToDegree(item.data.pose2d.yaw) + 'deg)',
                    zIndex: 9999
                  }"
                >
                  <div
                    style="
                      font-size: 0.6rem;
                      position: absolute;
                      top: 50%;
                      left: 40%;
                      transform: translateX(-50%) translateY(-50%) ;
                      color: greenyellow;
                    "
                  >
                    {{ item.robotNo || '' }}
                  </div>
                  <img
                    src="@/assets/imgs/indexPage/chache-4备份 7@2x.png"
                    style="width: 100%; height: 100%"
                  />
                </div>
              </div>
              <div
                class="indexpage-container-box-point-item"
                v-for="(item, index) in state.allMapPointInfo"
                :key="index"
                :style="{
                  left:
                    (Number(item.locationX) - Number(item.locationWidePx) / 2) * Number(radio) +
                    'px',
                  top:
                    (Number(item.locationY) - Number(item.locationDeepPx) / 2) * Number(radio) +
                    'px',
                  width: Number(item.locationWidePx) * Number(radio) + 'px',
                  height: Number(item.locationDeepPx) * Number(radio) + 'px'
                }"
              >
                <!-- 1 路径点 -->
                <el-tooltip class="box-item" effect="light" placement="top">
                  <template #content>
                    <div v-if="item.type === 2">
                      <div class="indexpage-popover-item">
                        <div> 库位号： </div>
                        <div>
                          {{ item.showData?.locationNo || '' }}
                        </div>
                      </div>
                      <div class="indexpage-popover-item">
                        <div> 所属线库： </div>
                        <div>
                          {{ item.showData?.laneName || '' }}
                        </div>
                      </div>
                      <div class="indexpage-popover-item">
                        <div> 所属区域： </div>
                        <div>
                          {{ item.showData?.areaName || '' }}
                        </div>
                      </div>
                    </div>
                    <div v-else-if="item.type === 3">
                      <div class="indexpage-popover-item">
                        <div> 设备编号： </div>
                        <div>
                          {{ item.showData?.deviceNo || '' }}
                        </div>
                      </div>
                      <div class="indexpage-popover-item">
                        <div> 设备类型： </div>
                        <div>
                          {{ item.showData ? filterTypeFun(item.showData.deviceType) : '' }}
                        </div>
                      </div>
                    </div>
                    <div v-else>
                      <div class="indexpage-popover-item">
                        <div> 节点类型： </div>
                        <div>{{
                          item.type == 1
                            ? '路径点'
                            : item.type == 4
                              ? '停车点'
                              : item.type == 5
                                ? '区域变更点'
                                : item.type == 6
                                  ? '等待点'
                                  : ''
                        }}</div>
                      </div>
                    </div>
                  </template>
                  <div
                    v-if="item.type === 1"
                    :style="{
                      width: Number(item.locationWidePx) * Number(radio) + 'px',
                      height: Number(item.locationDeepPx) * Number(radio) + 'px',
                      backgroundColor: '#000',
                      borderRadius: '50%'
                    }"
                  >
                  </div>
                  <!-- 库位点 -->
                  <img
                    v-else-if="item.type === 2"
                    :src="item.imgUrl"
                    :style="nodeStyle(item, index)"
                    @dblclick="storeClick(item)"
                  />
                  <!-- 设备点 -->
                  <img
                    v-else-if="item.type === 3"
                    :src="
                      item.formattedData.mapImageUrl ||
                      'https://api.znkjfw.com/admin-api/infra/file/4/get/设备点_png_179_1739327151877.png'
                    "
                    :style="nodeStyle(item, index)"
                  />
                  <!-- 停车点 -->
                  <img
                    v-else-if="item.type === 4"
                    :src="
                      item.formattedData.mapImageUrl ||
                      'https://api.znkjfw.com/admin-api/infra/file/4/get/停车场-01_png_179_1739326933020.png'
                    "
                    :style="nodeStyle(item, index)"
                  />
                  <!-- 路径点 -->
                  <img
                    v-else-if="item.type === 5"
                    :src="
                      item.formattedData.mapImageUrl ||
                      'https://api.znkjfw.com/admin-api/infra/file/4/get/区域_png_179_1739327151876.png'
                    "
                    :style="nodeStyle(item, index)"
                  />
                  <!-- 等待点 -->
                  <img
                    v-else-if="item.type === 6"
                    :src="
                      item.formattedData.mapImageUrl ||
                      'https://api.znkjfw.com/admin-api/infra/file/4/get/等待点_png_179_1739326991439.png'
                    "
                    :style="nodeStyle(item, index)"
                  />
                </el-tooltip>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>

  <!-- 左下角图层 -->
  <div class="affix-container-left" v-if="!isAllBoard">
    <div class="affix-container-left-box">
      <div
        class="affix-container-left-box-item-box"
        :style="{
          height: legendObj.legendShow ? '84px' : '0',
          overflow: 'hidden',
          transition: 'all 0.3s ease-in-out'
        }"
      >
        <div class="affix-container-left-box-item">
          <div class="affix-container-left-box-item-left"> 行驶路线 </div>
          <img
            src="@/assets/imgs/indexPage/yanjing_xianshi_o.png"
            class="affix-container-left-box-item-img"
            v-if="legendObj.driveLineShow"
            @click="changDriveLineShow"
          />
          <img
            src="@/assets/imgs/indexPage/yanjing_yincang_o.png"
            class="affix-container-left-box-item-img"
            v-if="!legendObj.driveLineShow"
            @click="changDriveLineShow"
          />
        </div>
        <div class="affix-container-left-box-item">
          <div class="affix-container-left-box-item-left"> 车辆 </div>
          <img
            src="@/assets/imgs/indexPage/yanjing_xianshi_o.png"
            class="affix-container-left-box-item-img"
            v-if="legendObj.carShow"
            @click="changCarShow"
          />
          <img
            src="@/assets/imgs/indexPage/yanjing_yincang_o.png"
            class="affix-container-left-box-item-img"
            v-if="!legendObj.carShow"
            @click="changCarShow"
          />
        </div>
      </div>
      <div
        class="affix-container-left-box-item-bottom"
        @click="legendObj.legendShow = !legendObj.legendShow"
      >
        <div class="affix-container-left-box-item-bottom-left"> 图例 </div>
        <img
          src="@/assets/imgs/indexPage/zhankai@2x.png"
          class="affix-container-left-box-item-bottom-img"
          :style="{
            transform: legendObj.legendShow ? 'rotate(180deg)' : 'rotate(0deg)',
            transition: 'all 0.3s ease-in-out'
          }"
        />
      </div>
    </div>
  </div>

  <!-- 右下角的功能 -->
  <div class="affix-container-right" v-if="!isAllBoard">
    <!-- 拖拽 -->
    <div class="item" @click="changeIsDrag">
      <img src="@/assets/imgs/indexPage/编组 12.png" style="width: 100%; height: 100%" />
    </div>
    <!-- 放大 -->
    <div class="item">
      <img
        src="@/assets/imgs/indexPage/编组 14.png"
        style="width: 100%; height: 100%"
        @click="changeSizeRaio('add')"
      />
    </div>
    <!-- 缩小 -->
    <div class="item">
      <img
        src="@/assets/imgs/indexPage/编组 15.png"
        style="width: 100%; height: 100%"
        @click="changeSizeRaio('sub')"
      />
    </div>
    <!-- 全屏 -->
    <div class="item">
      <img
        src="@/assets/imgs/indexPage/编组 22.png"
        style="width: 100%; height: 100%"
        @click="toggleFullScreen"
      />
    </div>
  </div>
  <storeDialog ref="storeDialogRef" @success="emitParent" />
  <carDialog ref="carDialogRef" />
</template>

<script setup>
import {
  ref,
  defineComponent,
  reactive,
  nextTick,
  onMounted,
  onBeforeUnmount,
  onUnmounted
} from 'vue'
import * as MapApi from '@/api/map/map'
import WebSocketClient from '../webSocket.js'
import storeDialog from './storeDialog.vue'
import { color } from 'echarts'
import { resetDragPosition } from '@/utils/drag'
import carDialog from './carDialog.vue'
import { is } from 'bpmn-js/lib/util/ModelUtil'
import JSONBigInt from 'json-bigint'
import { propTypes } from '@/utils/propTypes'
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'

const message = useMessage() // 消息弹窗

const carDialogRef = ref(null)
const socketClient = ref(null)
const router = useRouter() // 路由对象
const emit = defineEmits(['transmitMapId'])
const storeDialogRef = ref(null) // 仓库信息弹窗
const list = ref([])
const testCarList = ref([]) //小车数组
const carWidth = ref(200)
const carHeight = ref(100)

// 定义属性
const props = defineProps({
  isAllBoard: propTypes.bool.def(false), // 当前选中的链接
  isFullScreen: {
    type: Boolean,
    default: () => false
  }
})

//节点样式
const nodeStyle = (item, index) => {
  return {
    verticalAlign: 'top',
    objectFit: 'cover',
    width: Number(item.locationWidePx) * Number(radio.value) + 'px',
    height: Number(item.locationDeepPx) * Number(radio.value) + 'px'
  }
}
//返回设备类型
const filterTypeFun = (deviceType) => {
  let list = getIntDictOptions(DICT_TYPE.DEVICE_TYPE)
  let deviceItem = list.find((item) => {
    return item.value == deviceType
  })
  return deviceItem.label
}

const convertActualToBrowser = (pointX, pointY) => {
  let resolution = Number(imgBgObj.resolution)
  let origin = imgBgObj.origin

  const y1 = Number(origin[1]) + Number(imgBgObj.height) * resolution
  let x = Math.max(Number(pointX) - Number(origin[0]), 0)
  let y = Math.max(y1 - Number(pointY), 0)

  return {
    x: x / resolution - carWidth.value / resolution / 100 / 2,
    y: y / resolution - carHeight.value / resolution / 100 / 2
  }
}

//全屏
const isFull = ref(false)

//是否可以拖拽
const isDrag = ref(false)
const changeIsDrag = () => {
  nextTick(() => {
    isDrag.value = !isDrag.value
    if (!isDrag.value) {
      //还原位置
      resetPosition()
    }
  })
}

//点击选中线  如果选中就变成非选中 否则相反
const handleChooseRoute = (val, i) => {
  if (lineList.value.length) {
    if (val.isSelect) {
      lineList.value.forEach((item, index) => {
        if (index == i) {
          item.isSelect = false
        } else {
          item.isSelect = false
        }
      })
    } else {
      lineList.value.forEach((item, index) => {
        if (index == i) {
          item.isSelect = true
        } else {
          item.isSelect = false
        }
      })
    }
  }
}

// 获取曲线的路径
const getCurvePath = (curve) => {
  let startPointX = Number(curve.startPointX) * radio.value
  let startPointY = Number(curve.startPointY) * radio.value
  let endPointX = Number(curve.endPointX) * radio.value
  let endPointY = Number(curve.endPointY) * radio.value
  return `M ${startPointX} ${startPointY} C ${curve.beginControlX * radio.value} ${curve.beginControlY * radio.value}, ${curve.endControlX * radio.value} ${curve.endControlY * radio.value}, ${endPointX} ${endPointY}`
}

//放大缩小
const isSizeRadio = ref(1)
const changeSizeRaio = (type) => {
  if (type == 'add') {
    if (isSizeRadio.value < 4) {
      isSizeRadio.value += 0.1
    } else {
      isSizeRadio.value = 3.9
      message.warning('不能在放大了')
    }
  } else {
    if (isSizeRadio.value > 0.4) {
      isSizeRadio.value -= 0.1
    } else {
      isSizeRadio.value = 0.3
      message.warning('不能在缩小了')
    }
  }
}
//图层状态
const legendObj = reactive({
  driveLineShow: true,
  carShow: true,
  legendShow: true
})
// 车辆是否显示
const changCarShow = () => {
  legendObj.carShow = !legendObj.carShow
}
// 车辆行驶路线是否展示
const changDriveLineShow = () => {
  legendObj.driveLineShow = !legendObj.driveLineShow
}
const toggleFullScreen = () => {
  var elem = document.getElementById('indexpage-container') // 获取元素
  if (!document.fullscreenElement) {
    // 检查是否已经是全屏模式
    if (elem.requestFullscreen) {
      // 支持requestFullscreen API的标准方式
      elem.requestFullscreen().catch((err) => {
        alert(`无法进入全屏模式: ${err.message}`) // 处理错误情况
      })
    } else if (elem.mozRequestFullScreen) {
      // 旧版Firefox的API名称（已废弃）
      elem.mozRequestFullScreen()
    } else if (elem.webkitRequestFullscreen) {
      // WebKit/Safari/Chrome的API名称（已废弃）
      elem.webkitRequestFullscreen()
    } else if (elem.msRequestFullscreen) {
      // IE/Edge的API名称（已废弃）
      elem.msRequestFullscreen()
    }
    isDrag.value = true
  } else {
    // 退出全屏模式
    if (document.exitFullscreen) {
      // 标准API退出全屏模式
      document.exitFullscreen()
    } else if (document.mozCancelFullScreen) {
      // 旧版Firefox的API名称（已废弃）
      document.mozCancelFullScreen()
    } else if (document.webkitExitFullscreen) {
      // WebKit/Safari/Chrome的API名称（已废弃）
      document.webkitExitFullscreen()
    } else if (document.msExitFullscreen) {
      // IE/Edge的API名称（已废弃）
      document.msExitFullscreen()
    }
    console.log('退出全屏')
    isDrag.value = false
    resetPosition()
  }
  // 监听全屏状态变化事件
  document.addEventListener('fullscreenchange', function () {
    if (!document.fullscreenElement) {
      // 在这里可以添加退出全屏后的逻辑
      isDrag.value = false
      isFull.value = false
      radio.value = 1
      resetPosition()
    } else {
      // 在这里可以添加进入全屏后的逻辑
      isDrag.value = true
      isFull.value = true
      nextTick(() => {
        let width = getElementWidthByClass('affix-container')
        radio.value = width / imgBgObj.width
      })
    }
  })

  // 监听旧版浏览器的全屏状态变化事件
  document.addEventListener('mozfullscreenchange', function () {
    if (!document.mozFullScreenElement) {
      console.log('已退出全屏模式 (Firefox旧版)')
      isDrag.value = false
      resetPosition()
    } else {
      console.log('已进入全屏模式 (Firefox旧版)')
      isDrag.value = true
    }
  })

  document.addEventListener('webkitfullscreenchange', function () {
    if (!document.webkitFullscreenElement) {
      console.log('已退出全屏模式 (WebKit旧版)')
      isDrag.value = false
      resetPosition()
    } else {
      console.log('已进入全屏模式 (WebKit旧版)')
      isDrag.value = true
    }
  })

  document.addEventListener('msfullscreenchange', function () {
    if (!document.msFullscreenElement) {
      console.log('已退出全屏模式 (IE/Edge旧版)')
      isDrag.value = false
      resetPosition()
    } else {
      console.log('已进入全屏模式 (IE/Edge旧版)')
      isDrag.value = true
    }
  })
}

//库位双击
const storeClick = async (item) => {
  let storeData = await MapApi.houseLocationGetByMapItemId({
    mapId: item.positionMapId,
    mapItemId: item.id
  })
  storeDialogRef.value.open(JSON.parse(JSON.stringify(storeData)))
}
const lineList = ref([])
const pointList = ref([])

//将节点实际宽高cm转换成px
const cmConversionPx = (cWidth, cHeight) => {
  let pWidth = Number(cWidth) / Number(imgBgObj.resolution) / 100
  let pHeight = Number(cHeight) / Number(imgBgObj.resolution) / 100
  return {
    pWidth,
    pHeight
  }
}

const draggableElement = ref(null)
const resetPosition = () => {
  if (draggableElement.value) {
    resetDragPosition(draggableElement.value)
  }
}
// 计算直线中间箭头的路径
const getLineMidArrowPath = (item) => {
  const midX = ((Number(item.startPointX) + Number(item.endPointX)) / 2) * radio.value
  const midY = ((Number(item.startPointY) + Number(item.endPointY)) / 2) * radio.value

  let dx = item.endPointX * radio.value - item.startPointX * radio.value
  let dy = item.endPointY * radio.value - item.startPointY * radio.value
  let length = Math.sqrt(dx * dx + dy * dy)

  if (length === 0) {
    return `M ${midX} ${midY} L ${midX} ${midY}`
  }

  const unitDx = dx / length
  const unitDy = dy / length

  const arrowLength = 1
  const startXArrow = midX - unitDx * arrowLength
  const startYArrow = midY - unitDy * arrowLength
  const endXArrow = midX
  const endYArrow = midY

  return `M ${startXArrow} ${startYArrow} L ${endXArrow} ${endYArrow}`
}
const calculateDistanceAndAngle = (point1, point2) => {
  // 计算水平和垂直方向的差值
  const dx = point2.left - point1.left
  const dy = point2.top - point1.top

  // 计算两点之间的长度（使用勾股定理）
  const distance = Math.sqrt(dx * dx + dy * dy)

  // 计算两点连线与水平轴正方向的夹角（弧度）
  const angleInRadians = Math.atan2(dy, dx)

  // 将弧度转换为角度
  const angleInDegrees = angleInRadians * (180 / Math.PI)

  return {
    distance: distance,
    angle: angleInDegrees,
    left: point1.left,
    top: point1.top
  }
}

const formatTypeImg = (type) => {
  switch (type) {
    case 1:
      return ''
    case 2:
      return 'https://api.znkjfw.com/admin-api/infra/file/4/get/库位库存_png_179_1739326653035.png'
    case 3:
      return 'https://api.znkjfw.com/admin-api/infra/file/4/get/设备点_png_179_1739327151877.png'
    case 4:
      return 'https://api.znkjfw.com/admin-api/infra/file/4/get/停车场-01_png_179_1739326933020.png'
    case 5:
      return 'https://api.znkjfw.com/admin-api/infra/file/4/get/区域_png_179_1739327151876.png'
    case 6:
      return 'https://api.znkjfw.com/admin-api/infra/file/4/get/等待点_png_179_1739326991439.png'
    default:
      return ''
  }
}
const replaceHttpWithWs = (str) => {
  return str.replace(/^http/, 'ws')
}
// 连接websocket
const linkWebSocket = (url) => {
  socketClient.value = new WebSocketClient(url)
  if (socketClient.value) {
    // 监听消息
    socketClient.value.onMessage((message) => {
      //心跳信息不处理
      if (message == 'ping' || message == 'pong') return
      let jsonMsg = JSON.parse(message)
      // 车辆信息
      if (jsonMsg.type == 'map_push') {
        let data = JSON.parse(jsonMsg.content)
        let dataList = []
        for (let key in data) {
          dataList.push({
            macAddress: key,
            data: JSON.parse(data[key])
          })
        }

        // testCarList.value = JSON.parse(JSON.stringify(dataList))
        // testCarList.value = mergeCarArrays(testCarList.value, dataList)
        testCarList.value = mergeArraysWithoutDelete(testCarList.value, dataList)
       
        testCarList.value.forEach((item) => {
        item.originWidth = imgBgObj.width
        item.originHeight = imgBgObj.height
        item.origin = imgBgObj.origin
        item.realX = convertActualToBrowser(item.data.pose2d.x, item.data.pose2d.y).x
        item.realY = convertActualToBrowser(item.data.pose2d.x, item.data.pose2d.y).y
        item.robotNo =item.data.pose2d.robotNo
      })

        // console.log(testCarList.value)
      }
      //告警信息
      if (jsonMsg.type == 'agv_warn') {
        ElMessage({
          message: () =>
            h(
              'div',
              {
                style: 'background-color: #C60606;'
              },
              [
                h(
                  'span',
                  { style: 'color: rgba(255,255,255,0.88);font-size: 14px;' },
                  `${JSON.parse(jsonMsg.content)}`
                ),
                h(
                  'span',
                  {
                    onClick: () => lookError(),
                    style:
                      'color: rgba(255,255,255,0.88);font-size: 14px;cursor: pointer;text-decoration-line: underline;margin-left: 32px;'
                  },
                  '详情'
                )
              ]
            ),
          showClose: false,
          duration: 3000, // 让消息持续显示，直到用户关闭
          type: 'info',
          customClass: 'indexpage-custom-message-style'
        })
      }
      // 规划路线信息
      if (jsonMsg.type == 'planning_move_pose') {
        let data = JSON.parse(jsonMsg.content)
        // console.log('======规划路线======', JSON.parse(data).data)
        let dataList = JSON.parse(data).data
        if (lineList.value.length > 0) {
          // console.log(lineList.value)
          lineList.value = setIsSelect(lineList.value, dataList)
        }
      }
    })
  }
}
// 现在车辆的逻辑是这样  websoket map_push类型推送消息 每次推送新车 我就添加到车辆列表中 testCarList 不删除车辆 
// 每几秒轮询调用查看当前楼层区域的在线车辆 如果不存在 则再把testCarList 中的车辆删除
const robotByFloorAndAreaList = ref([]) // 机器人列表  
const robotListTimer = ref(5) //轮询时间
const robotListTimerRef = ref(null) //轮询定时器 
const getRobotByFloorAndAreaList =  () => {
  if(robotListTimerRef.value){
    clearInterval(robotListTimerRef.value)
    robotListTimerRef.value = null
  }
  // robotByFloorAndAreaList.value = []
  robotListTimerRef.value = setInterval(() => {
    MapApi.getRobotByFloorAndArea({ floor: imgBgObj.floor, area: imgBgObj.area }).then((res) => {
      // console.log(res)
      robotByFloorAndAreaList.value = res
      if(testCarList.value.length){
        testCarList.value = filterArrayByRobotNo(testCarList.value, robotByFloorAndAreaList.value)
      }
    })
  }, robotListTimer.value * 1000)
}

// 删掉不在线的车辆
const filterArrayByRobotNo = (arr1, arr2) =>{
    return arr1.filter(item => {
        const robotNo = item.data.pose2d.robotNo;
        return arr2.includes(robotNo);
    });
}


const mergeCarArrays = (arr1, arr2) => {
  const result = []
  const macAddressSet = new Set()
  // 先处理第一个数组中原本就有的元素，进行更新或保留
  for (const item1 of arr1) {
    const macAddress1 = item1.macAddress
    macAddressSet.add(macAddress1)
    let foundInSecond = false
    for (const item2 of arr2) {
      const macAddress2 = item2.macAddress
      if (macAddress1 === macAddress2) {
        foundInSecond = true
        // 更新pose2d信息
        item1.data.pose2d = item2.data.pose2d
        result.push(item1)
        break
      }
    }
    if (!foundInSecond) {
      // 如果没在第二个数组中找到，就不添加到结果中，相当于删除
      continue
    }
  }
  // 再处理第二个数组中存在但第一个数组中不存在的元素，添加到结果中
  for (const item2 of arr2) {
    const macAddress2 = item2.macAddress
    if (!macAddressSet.has(macAddress2)) {
      result.push(item2)
    }
  }
  return result
}
const mergeArraysWithoutDelete = (arr1, arr2) => {
  // 复制第一个数组，避免修改原始数组
  const result = [...arr1]
  // 遍历第二个数组
  for (const item2 of arr2) {
    const macAddress2 = item2.macAddress
    let found = false
    // 遍历结果数组，查找是否存在相同 macAddress 的元素
    for (let i = 0; i < result.length; i++) {
      const item1 = result[i]
      const macAddress1 = item1.macAddress
      if (macAddress1 === macAddress2) {
        // 若存在相同 macAddress 的元素，更新其 pose2d 信息
        result[i].data.pose2d = item2.data.pose2d
        found = true
        break
      }
    }
    // 若未找到相同 macAddress 的元素，将该元素添加到结果数组中
    if (!found) {
      result.push(item2)
    }
  }
  return result
}

const setIsSelect = (arr1, arr2) => {
  for (let i = 0; i < arr1.length; i++) {
    const element = arr1[i]
    const isExist = arr2.includes(element.id)
    element.isSelect = isExist
  }
  return arr1
}

// 查看更多异常列表
const lookError = () => {
  router.push({
    path: '/carError'
  })
}
// 发送websocket消息
const sendMessage = () => {
  socketClient.value.send('Hello, WebSocket!')
}
// 断开连接
const disconnect = () => {
  socketClient.value.disconnect()
}
const emitParent = () => {
  getMapData(imgBgObj)
}

//获取扫描图  地图背景相关的信息
const imgBgObj = reactive({
  imgUrl: '',
  positionMapId: '',
  width: '',
  height: '',
  floor: '',
  area: '',
  resolution: 0,
  origin: null
})
const getMapData = async (item) => {
  let yamlJson = JSON.parse(item.yamlJson)
  imgBgObj.positionMapId = item.id
  imgBgObj.floor = item.floor
  imgBgObj.area = item.area
  imgBgObj.width = yamlJson.width
  imgBgObj.height = yamlJson.height
  imgBgObj.origin = yamlJson.origin
  imgBgObj.resolution = yamlJson.resolution
  //获取地图
  getMapDownloadPng(imgBgObj)
  //初始化Websocket
  initWebsocket()
}
const getMapDownloadPng = async (mapInfo) => {
  let data = await MapApi.getPositionMapdDwnloadPngBase64({
    floor: mapInfo.floor,
    area: mapInfo.area
  })
  imgBgObj.imgUrl = data

  //获取节点 路径等信息
  await getAllNodeList()
  await getAllMapRoute()
  await computedRatio()
  await getRobotByFloorAndAreaList()
}
const initWebsocket = () => {
  let websocketUrl = `${replaceHttpWithWs(import.meta.env.VITE_BASE_URL)}/infra/ws?type=map&floor=${imgBgObj.floor}&area=${imgBgObj.area}`
  linkWebSocket(websocketUrl)
}
const computedRatio = () => {
  nextTick(() => {
    if (props.isFullScreen) {
      let width = getElementWidthByClass('index-page-container')

      testCarList.value.forEach((item) => {
        item.originWidth = imgBgObj.width
        item.originHeight = imgBgObj.height
        item.origin = imgBgObj.origin
        item.realX = convertActualToBrowser(item.data.pose2d.x, item.data.pose2d.y).x
        item.realY = convertActualToBrowser(item.data.pose2d.x, item.data.pose2d.y).y
      })

      radio.value = width / imgBgObj.width
      imgBgObj.width = imgBgObj.width * radio.value
      imgBgObj.height = imgBgObj.height * radio.value

      // console.log("====",testCarList.value)
    }
  })
}

//偏航率斜率算旋转
const radianToDegree = (radian) => {
  const degree = radian * (180 / Math.PI)
  return `${degree}`
}

const state = reactive({
  mapRouteList: [],
  allMapPointInfo: []
})
const radio = ref(1) //放大缩小的倍数

// 获取地图连线
const getAllMapRoute = async () => {
  state.mapRouteList = await MapApi.getPositionMapLineByPositionMapId(imgBgObj.positionMapId)
}
//获取节点
const getAllNodeList = async (positionMapId) => {
  state.allMapPointInfo = await MapApi.getPositionMapItemList({
    positionMapId: imgBgObj.positionMapId
  })
  state.allMapPointInfo?.forEach((item) => {
    item.formattedData = item.dataJson ? JSON.parse(item.dataJson) : ''
    item.showData = item.dataJson
      ? item.type == 2
        ? JSON.parse(item.dataJson)[0]
        : JSON.parse(item.dataJson)
      : null
    item.imgUrl = formatTypeImg(item.type)

    if (item.type === 1) {
      item.locationDeep = 40
      item.locationWide = 40
    } else if (item.type === 5 || item.type === 6) {
      item.locationDeep = 150
      item.locationWide = 150
    } else if (item.type === 2) {
      //库位点
      item.dataList = JSONBigInt({ storeAsString: true }).parse(item.dataJson)
      item.locationDeep = item.dataList[0].locationDeep
      item.locationWide = item.dataList[0].locationWide
    } else if (item.type === 3) {
      item.dataObj = JSONBigInt({ storeAsString: true }).parse(item.dataJson)
      item.locationDeep = item.dataObj.locationDeep
      item.locationWide = item.dataObj.locationWide
    } else if (item.type === 4) {
      item.dataObj = JSONBigInt({ storeAsString: true }).parse(item.dataJson)
      item.locationDeep = item.dataObj.locationDeep
      item.locationWide = item.dataObj.locationWide
    }
    //要将实际的cm改成px
    if (item.locationWide && item.locationDeep) {
      let pxObj = cmConversionPx(item.locationWide, item.locationDeep)
      item.locationWidePx = pxObj.pWidth
      item.locationDeepPx = pxObj.pHeight
    }
  })
}

//鼠标滚轮
const handleWheel = (event) => {
  // 判断 Ctrl 键是否被按下
  if (event.ctrlKey && !props.isFullScreen) {
    // 阻止默认的滚动行为
    event.preventDefault()

    // 根据滚轮滚动方向调整缩放比例
    if (event.deltaY < 0) {
      // 向上滚动，放大
      //放大
      if (isSizeRadio.value < 4) {
        isSizeRadio.value += 0.1
      } else {
        isSizeRadio.value = 3.9
        message.warning('不能在放大了')
      }
    } else {
      //缩小
      if (isSizeRadio.value > 0.4) {
        isSizeRadio.value -= 0.1
      } else {
        isSizeRadio.value = 0.3
        message.warning('不能在缩小了')
      }
    }
  }
}

const convertToFrontendCoordinates = (origin, width, height, target) => {
  // 提取原点的 x 和 y 坐标
  const [originX, originY] = origin
  // 提取目标点的 x 和 y 坐标
  const [targetX, targetY] = target

  // 计算目标点相对于原点在 x 方向上的偏移量
  const offsetX = targetX - originX
  // 计算目标点相对于原点在 y 方向上的偏移量
  const offsetY = targetY - originY

  // 计算前端页面中的 left 坐标
  const left = offsetX
  // 计算前端页面中的 top 坐标，需要考虑坐标系的转换
  const top = height - offsetY

  return {
    top,
    left,
    origin
  }
}
const getImageWidth = (imageUrl, name) => {
  return new Promise((resolve, reject) => {
    const img = new Image()
    img.onload = function () {
      resolve(img[name])
    }
    img.onerror = function () {
      reject(new Error('图片加载失败'))
    }
    img.src = imageUrl
  })
}

const getElementWidthByClass = (className) => {
  const element = document.querySelector(`.${className}`)
  if (element) {
    const widthWithUnit = window.getComputedStyle(element).width
    return widthWithUnit.slice(0, -2)
  }
  return null
}
//小车双击
const carDbClick = (item, index) => {
  carDialogRef.value.open(JSON.parse(JSON.stringify(item)))
}

defineExpose({ getMapData }) // 提供 open 方法，用于打开弹窗
onMounted(() => {})
onBeforeUnmount(() => {
  // console.log('onBeforeUnmount')
  if(robotListTimerRef.value){
    clearInterval(robotListTimerRef.value)
    robotListTimerRef.value = null
  }
})
</script>

<style lang="scss" scoped>
.index-page {
  width: 100%;
  .index-page-container {
    width: 100%;
    position: relative;
  }

  .is-full-screen {
    height: calc(100vh - 8.125rem) !important;
    overflow: auto;
  }
}

.affix-container {
  width: 100%;
  position: relative;
}
.indexpage-container {
  width: 100%;
  position: relative;
}
.indexpage-container-active {
  width: 100%;
  position: relative;
  cursor: grab;
}
.indexpage-container-active:active {
  cursor: grabbing;
}
.indexpage-container .affix-container-top {
  width: 100%;
  height: 80px;
  background-color: #fff;
  border-bottom: 1px solid #f5f5f5;
}
.indexpage-container-box-point {
  width: 100%;
  position: absolute;
  top: 0;
  left: 0;
  bottom: 0;
  right: 0;
}
.indexpage-container-box-point-item {
  box-sizing: border-box;
  position: absolute;
  cursor: pointer;
}
.scrollbar-flex-content {
  padding: 2px 6px;
  display: flex;
  align-items: center;
  flex-wrap: wrap;
}
.scrollbar-demo-item {
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 90px;
  height: 30px;
  margin: 10px 6px;
  text-align: center;
  border-radius: 4px;
  background: var(--el-color-primary-light-9);
  color: var(--el-color-primary);
  position: relative;
}
.scrollbar-demo-item {
  cursor: pointer;
  border: none;
}

:focus-visible {
  outline: none;
}
.indexpage-container-box {
  width: 100%;
  position: relative;
}
.indexpage-container-box-img {
  width: 100%;
  height: auto;
}
.indexpage-popover-item {
  display: flex;
  font-family:
    PingFangSC,
    PingFang SC;
  font-weight: 400;
  font-size: 14px;
  color: #0d162a;
  padding: 3px;
}
.line-box {
  position: absolute;
}
.indexpage-car-item {
  position: absolute;
  cursor: pointer;
}
.affix-container-left {
  position: fixed;
  right: 30px;
  bottom: 70px;
  z-index: 999;

  .affix-container-left-box {
    width: 144px;
  }
  .affix-container-left-box-item-box {
    width: 100%;
    border-bottom: 1px solid #eeeeee;
    background: #ffffff;
  }
  .affix-container-left-box-item {
    width: 100%;
    padding: 0 18px;
    height: 42px;
    display: flex;
    align-items: center;
    justify-content: space-between;
  }
  .affix-container-left-box-item-left {
    font-family:
      PingFangSC,
      PingFang SC;
    font-weight: 400;
    font-size: 14px;
    color: rgba(0, 0, 0, 0.88);
  }
  .affix-container-left-box-item-img {
    cursor: pointer;
    flex-shrink: 0;
    width: 20px;
    height: 12px;
  }
  .affix-container-left-box-item-bottom {
    width: 100%;
    height: 36px;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    background: #ffffff;
  }
  .affix-container-left-box-item-bottom-img {
    cursor: pointer;
    flex-shrink: 0;
    width: 12px;
    height: 7px;
  }
  .affix-container-left-box-item-bottom-left {
    cursor: pointer;
    flex-shrink: 0;
    font-family:
      PingFangSC,
      PingFang SC;
    font-weight: 400;
    font-size: 16px;
    color: #98a4bf;
    margin-right: 2px;
  }
}

.affix-container-right {
  position: fixed;
  z-index: 999;
  right: 30px;
  bottom: 20px;
  display: flex;
  align-items: center;
  justify-content: flex-end;

  .item {
    width: 30px;
    height: 30px;
    cursor: pointer;
    flex-shrink: 0;
    margin-left: 8px;
  }
}
</style>
