<template>
  <div class="h-100 stage">
    <!-- 主视图与画中画容器 -->
    <!-- MapBox 容器：作为主视图或小窗显示（始终挂载） -->
    <div
      v-show="mainView === 'map' || (mainView === 'video' && pipVisible)"
      class="stage-item map"
      :class="{ main: mainView === 'map', pip: mainView === 'video' && pipVisible }"
      :style="pipCssVars"
    >
      <map-box
        ref="mapbox"
        :enableShowNofly="true"
        :enableGuided="true"
        :enableFollow="true"
        :enableSwitch="mainView === 'map'"
        :enableZoom="mainView === 'map'"
        :enblueScale="!$store.state.app.isWideScreen"
        @longPress="handleLongPress"
        @map-ready="onMapReady"
      >
        <template #content>
          <!-- 仅在地图为主视图时渲染叠加控件（小窗时不渲染） -->
          <div v-if="mapReady && mainView === 'map'">
            <BatteryStatus :plane="plane" />
            <PlaneStatus :plane="plane" />
            <ControllerTabs :plane="plane" @mapXOffset="mapXOffset" @makeRoute="makeRoute" @clearRoute="clearRoute" />
          </div>
        </template>
      </map-box>
    </div>

    <!-- VideoBox 容器：作为主视图或小窗显示（始终挂载） -->
    <div
      v-show="mainView === 'video' || (mainView === 'map' && pipVisible)"
      class="stage-item video"
      :class="{ main: mainView === 'video', pip: mainView === 'map' && pipVisible }"
      :style="pipCssVars"
    >
      <video-box
        ref="videobox"
        fit="cover"
        :show-controls="false"
        width="100%"
        height="100%"
      >
        <template #content>
          <!-- 仅在视频为主视图时渲染叠加控件（小窗时不渲染） -->
          <div v-if="mainView === 'video'">
            <BatteryStatus :plane="plane" />
            <PlaneStatus :plane="plane" />
            <ControllerTabs :plane="plane" @mapXOffset="mapXOffset" @makeRoute="makeRoute" @clearRoute="clearRoute" />
          </div>
        </template>
      </video-box>
    </div>

    <!-- 顶部工具条：切换主视图 / 显示/隐藏 小窗 -->
    <div class="stage-toolbar top-right">
      <el-button size="mini" @click="toggleMainView">
        {{ mainView === 'map' ? '切到视频' : '切到地图' }}
      </el-button>
      <el-button size="mini" @click="pipVisible = !pipVisible">
        {{ pipVisible ? '隐藏小窗' : '显示小窗' }}
      </el-button>
    </div>

    <!-- 弹出框 -->
    <el-dialog :title="dialogTitle" :visible.sync="dialogVisible" width="320px" top="30vh" @close="closeCallback"
      @open="openCallback">
      <!-- 点飞设置弹出框 -->
      <template v-if="dialogItem == 'guidedBox'">
        <el-form label-position="left">
          <el-form-item label="纬度" label-width="80px">
            <el-input v-model="guidedLonLat.lat" placeholder="请输维度" label="纬度"></el-input>
          </el-form-item>
          <el-form-item label="经度" label-width="80px">
            <el-input v-model="guidedLonLat.lon" placeholder="请输经度" label="经度"></el-input>
          </el-form-item>
          <el-form-item label="高度" label-width="80px">
            <el-input-number v-model="guidedAlt" label="高度设置"></el-input-number>
            <font class="m-l-5">米</font>
          </el-form-item>
        </el-form>
        <span slot="footer" class="dialog-footer">
          <el-button size="medium" @click="dialogVisible = false">关闭</el-button>
          <el-button size="medium" type="primary" @click="() => {
            if (flyToSinglePlane(guidedLonLat.lon, guidedLonLat.lat, guidedAlt)) {
              isReserveGuidedMaker = true;
              dialogVisible = false;
            }
          }">
            飞至
          </el-button>
        </span>
      </template>
    </el-dialog>
  </div>
</template>

<script>
import MapBox from '@/components/MapBox'
import VideoBox from '@/components/VideoBox'
import ControllerTabs from '@/components/ControllerTabs'
import BatteryStatus from '@/components/BatteryStatus'
import PlaneStatus from '@/components/PlaneStatus'
import mqtt from '@/utils/mqtt'
import { waitForMapCanvasReady } from '@/utils'

export default {
  name: 'Planes',
  data () {
    return {
      // 视图与画中画状态
      mainView: 'map', // 'map' | 'video'
      pipVisible: true,
      pipPos: 'top-right', // 预留：'top-right'|'top-left'|'bottom-right'|'bottom-left'
      pipSize: { w: 400, h: 225 }, // 16:9 小窗尺寸
      dialogTitle: '', // 弹出框 标题
      dialogItem: '', // 弹出框 项目类型判断
      dialogVisible: false, // 弹出框 显隐
      guidedLonLat: {}, // 点飞 的经纬度
      guidedAlt: '', // 点飞的高度
      isReserveGuidedMaker: false, // 关闭指点飞行操作窗口时 标记是否删除图标
      planesId: this.$route.params.id,
      localCount: 0, // 本地存储计数器
      mapReady: false// 地图加载完成后 回调时 设置此值  让地图组件插槽内容 滞后显示
    }
  },
  components: {
    MapBox,
    VideoBox,
    ControllerTabs,
    BatteryStatus,
    PlaneStatus
  },
  computed: {
    pipCssVars () {
      const w = typeof this.pipSize.w === 'number' ? `${this.pipSize.w}px` : this.pipSize.w
      const h = typeof this.pipSize.h === 'number' ? `${this.pipSize.h}px` : this.pipSize.h
      return { '--pip-w': w, '--pip-h': h }
    },
    plane () {
      if (this.$store.state.airList.length > 0) {
        return this.$store.state.airList.find(plane => plane.id === this.planesId)
      }
      return null
    },
    planeState () {
      if (this.plane && this.plane.planeState) {
        return this.plane.planeState
      } else {
        return {}
      }
    },
    position () {
      if (this.plane) {
        if (this.plane.planeState.position.length > 0) {
          return this.plane.planeState.position
        } else {
          return []
        }
      } else {
        return []
      }
    },
    noflyData () {
      return this.$store.state.noflyData
    },
    ADSBList () {
      return this.$store.state.ADSBList
    },
    /**
     * @description: 侧边栏显隐
     */
    isCollapse () {
      return this.$store.state.app.isCollapse
    },
    /**
     * @description: 与图标选择强相关的轻量状态（仅当前选中飞机）
     */
    planeIconState () {
      const s = this.planeState || {}
      return {
        offline: s.online === false,
        run: !!s.hasGoods
      }
    }
  },

  methods: {
    /** 切换主视图 */
    toggleMainView () {
      this.mainView = this.mainView === 'map' ? 'video' : 'map'
      this.$nextTick(() => {
        // 主从切换后，通知地图自适应
        if (this.$refs.mapbox && typeof this.$refs.mapbox.handleResize === 'function') {
          this.$refs.mapbox.handleResize()
        }
      })
    },
    /** 弹出框 关闭事件回调 */
    closeCallback () {
      if (this.dialogItem === 'guidedBox' && this.isReserveGuidedMaker === false) { // 关闭点飞窗口时
        this.$refs.mapbox.delGuidedMarker()// 删除所有点飞的地图标记
        this.$refs.mapbox.clearMapElements(['guided-lines-layer', 'guided-center-point-layer'], ['guided-lines-source'])// 删除引导线
      }
      this.dialogVisible = false
      this.dialogItem = ''
    },
    /** 弹出框 打开事件回调 */
    openCallback () {
    },
    // 地图长按事件 记录地图经纬度
    handleLongPress (lonLat) {
      this.isReserveGuidedMaker = false
      this.dialogTitle = '指点飞行'
      this.dialogVisible = true
      this.dialogItem = 'guidedBox'
      this.guidedLonLat = lonLat // 设置点击的经纬度

      // 安全获取当前飞机位置和高度
      let center = { lon: 0, lat: 0 }
      let height = 0
      if (this.plane?.planeState?.position?.length > 0) {
        const lastPos = this.plane.planeState.position.at(-1)
        if (Array.isArray(lastPos)) {
          center = { lon: lastPos[0], lat: lastPos[1] }
          height = lastPos[2] || 0
        }
      }
      this.guidedAlt = height

      // 构造单架飞机的位置数组
      const planeCoords = [[center.lon, center.lat]]

      // 复用现有方法绘制引导线
      this.$refs.mapbox.drawGuidedLines({
        centerPoint: { lng: center.lon, lat: center.lat },
        endPoint: { lng: lonLat.lon, lat: lonLat.lat },
        planeCoords
      })
    },
    // 单架飞机点飞指令，参数：lon, lat, alt
    flyToSinglePlane (lon, lat, alt) {
      const lonNum = Number(lon)
      const latNum = Number(lat)
      const altNum = Number(alt)

      if (
        isNaN(lonNum) || isNaN(latNum) || isNaN(altNum) ||
        lonNum < -180 || lonNum > 180 ||
        latNum < -90 || latNum > 90
      ) {
        this.$message.warning('请输入有效的经纬度（经度-180~180，纬度-90~90）和高度')
        return false
      }

      const cmd = `{guidedMode:{lon:${lonNum.toFixed(7)},lat:${latNum.toFixed(7)},alt:${altNum.toFixed(1)}}}`
      this.publishFun(cmd)
      return true
    },
    // 地图组件回调地图加载完成后 执行
    onMapReady () {
      this.mapReady = true// 标记地图加载完成
      this.makePlane(this.plane)
    },
    /**
     * @description: 创建飞机图标
     */
    makePlane (plane) {
      let planeDefaultLonLat
      if (localStorage.getItem(plane.name)) { // 从本地缓存 拿飞机得初始位置
        planeDefaultLonLat = JSON.parse(localStorage.getItem(plane.name))
        plane.lon = planeDefaultLonLat.lon
        plane.lat = planeDefaultLonLat.lat
      } else {
        // 缺省 给经纬度 小数点后随机第五位 即有个10米左右的随机距离
        plane.lon = 100 + Number((Math.random() * 0.01).toFixed(5))
        plane.lat = 40 + Number((Math.random() * 0.01).toFixed(5))
      }
      this.$refs.mapbox.removePlanes()// 先清除画布上现有的飞机
      this.$refs.mapbox.makePlane(plane)// 创建飞机
      this.$refs.mapbox.goto({ lon: plane.lon, lat: plane.lat })// 跳转到飞机位置
    },
    /**
     * @description: 创建航线
     */
    makeRoute (routeData) {
      this.$refs.mapbox.makeRoute(routeData)
    },
    /**
     * @description: 清楚航线
     */
    clearRoute () {
      this.$refs.mapbox.clearRoute()
    },
    /**
     * @description: 屏幕横移
     * @param {*} val 正数向左移动 负数向右移动
     * @param {*} y 正数向上移动 负数向下移动
     */
    mapXOffset (x, y) {
      // 仅在地图为主视图时，才执行地图偏移
      if (this.mainView === 'map' && this.$refs.mapbox && typeof this.$refs.mapbox.mapXOffset === 'function') {
        this.$refs.mapbox.mapXOffset(x, y)
      }
    },
    /**
     * @description: 发布 mqtt 信息
     * @param {*} jsonData {'item':val} // item: questAss飞行航点任务 setQuestState 设置飞机状态  resetQuestState设置飞机初始状态 chan1油门通道1 chan2油门通道2  chan3油门通道3  chan4油门通道4 hookConteroller钩子控制 cameraController云台相机控制
     */
    publishFun (jsonData) {
      if (this.plane) {
        mqtt.publishFun(`cmd/${this.plane.macadd}`, jsonData)
      } else {
        this.$message.warning('与飞机通信未接通,请稍后')
      }
    }
  },
  mounted () {
  },
  watch: {
    // 这里不要deep:true 会一直新创飞机图标
    plane: {
      async handler () {
        try {
          // 等待地图画布准备好
          await waitForMapCanvasReady(this.$refs.mapbox.map)
          // 画布准备好后执行你自己的逻辑
          this.onMapReady()
          console.warn('飞机数据更新', this.plane)
        } catch (err) {
          console.debug('等待地图画布准备超时', err)
        }
      },
      immediate: true
    },
    // 实时更新飞机状态 到 到飞机弹出框
    planeState: {
      handler (val) {
        if (val) {
          val.name = this.plane.name // 保留飞机名称
          // 调用更新 popup 内容方法
          this.$refs.mapbox.updatePopupContent(val)
        }
      },
      deep: true
    },
    // 仅当离线/载重跨阈值状态发生变化时更新图标（当前选中飞机）
    planeIconState: {
      handler (val, oldVal) {
        const changed = !oldVal || oldVal.offline !== val.offline || oldVal.run !== val.run
        if (changed) {
          const stateObj = this.planeState || {}
          // 当前视图只有一架选中飞机，对应 MapBox 数组索引为 0
          this.$refs.mapbox.updatePlaneIcon(stateObj, 0)
        }
      },
      deep: false
    },
    /**
     * @description: 更新飞机位置 并画出轨迹 跟随飞机
     */
    position: {
      handler (val) {
        const len = val.length
        if (len > 2) {
          const lon = val[len - 1][0]
          const lat = val[len - 1][1]
          this.localCount++// 计数器 叠加
          if (this.localCount % 100 === 1) {
            localStorage.setItem(this.plane.name, `{ "lon": ${lon}, "lat": ${lat} }`)
          }
          this.$refs.mapbox.setPlaneLonLat({ lon: lon, lat: lat }, 0, val)// 更新飞机位置 并画出轨迹 跟随飞机
        }
      },
      deep: true
    },
    ADSBList: {
      handler (newList) {
        if (this.$refs.mapbox && typeof this.$refs.mapbox.makeADSBPlanes === 'function') {
          this.$refs.mapbox.makeADSBPlanes(newList)
        }
      },
      immediate: true,
      deep: true
    },
    /**
     * @description: 侧边栏缩进有变化时 地图重新自适应
     */
    isCollapse: {
      handler (val) {
        if (val) {
          setTimeout(() => {
            this.$nextTick(() => {
              this.$refs.mapbox.handleResize()
            })
          }, 500)
        }
      },
      deep: true
    }
  }
}

</script>

<style lang="scss" scoped>
.stage {
  position: relative;
}
.stage-item {
  position: absolute;
  overflow: hidden;
  transition: all .2s ease;
}
.stage-item.main {
  inset: 0;
  z-index: 10;
  border-radius: 0;
  box-shadow: none;
}
.stage-item.pip {
  width: var(--pip-w, 400px);
  height: var(--pip-h, 225px);
  z-index: 20;
  border-radius: 8px;
  box-shadow: 0 8px 24px rgba(0,0,0,.25);
}
/* 小窗位置：在右上基础上下移28px、左移43px */
.stage-item.pip {
  top: 40px;   /* 12 + 28 */
  right: 55px; /* 12 + 43 */
}

/* 工具条也移动到相应位置（与小窗同样偏移） */
.stage-toolbar.top-right {
  top: 40px;   /* 12 + 28 */
  right: 55px; /* 12 + 43 */
}

.stage-toolbar {
  position: absolute;
  z-index: 30;
  display: flex;
  gap: 8px;
}

/* 当地图为主视图时，避免叠加控件大面积拦截地图交互 */
/* 仅对 map 主视图容器内的控件做定向约束 */
.stage .map :deep(.mainBox) {
  pointer-events: none; /* 默认不拦截，让地图可拖拽 */
}
.stage .map :deep(.mainBox .taButGroup),
.stage .map :deep(.mainBox .tabContent),
.stage .map :deep(.el-dialog),
.stage .map :deep(.el-button),
.stage .map :deep(.el-slider),
.stage .map :deep(.el-input),
.stage .map :deep(.el-select) {
  pointer-events: auto; /* 仅在具体控件上启用交互 */
}

/* 确保电量条、状态面板只占据自身区域，且可交互 */
.stage .map :deep(.batteryBar),
.stage .map :deep(.plane-mode),
.stage .map :deep(.mainBox .tag) {
  pointer-events: auto;
}
</style>
