<!--
  文件描述：工具条
  创建时间：2024/4/16 10:54
  创建人：Zhaipeixiu
-->
<script setup>
import {ChevronBack,ChevronForward, CreateOutline, DuplicateSharp, EyeSharp, Layers, Settings} from '@vicons/ionicons5'
import {RulerAlt} from '@vicons/carbon'
import {TerrainSharp} from '@vicons/material'
import {DrawPolygon} from '@vicons/fa'
import {useMessage} from 'naive-ui'
import {ref, defineEmits} from "vue";
import {useStaticStore} from "@/store/staticOptions.js";
import {dataProcess_fromQT, dataProcess_fromQT_route} from "@/assets/js/websocketProtocol.ts";
import SpatialAnalysis from "@/components/SpatialAnalysis.vue";
import LayerManager from "@/components/map/LayerManager.vue";
import CollisionDetection from "./CollisionDetection.vue"
import {useLayerStore} from "@/store/layerManagerStore.ts";
import {Cartesian3} from "cesium";
import {ByDirectionAndLen, getDistance, getElevation} from "@/utils/map/geocomputation.ts";
import RouteManageViewer from "@/assets/js/RouteManageViewer.js";
import RouteOptions from "@/components/RouteOptions.vue";
import {useRouteStore} from "@/store/RouteStore";
import MarkerDialog from "@/components/MarkerDialog.vue";
import { useRouter, useRoute } from 'vue-router'
const router = useRouter()
const route = useRoute()

const emit = defineEmits(['resizeMap'])
const message = useMessage();
let SceneValue;
let showModal = ref(false);
let showRouteModal = ref(false);
let hasPlane = ref(false);
let showDetection = ref(false);
let store = useStaticStore();
let lStore = useLayerStore();
let groundHeight = ref(-1)
let detectDivHeight = ref(25)
const spatialAnalyse = ref(null)
const layerManager = ref(null)
const collisionDetection = ref(null)
const markerDialog = ref(null)

SceneValue = ref('untrace');
let frameCount = 0
let lastPos = undefined;  //飞机上一时点的坐标
function handleSceneSelect(key){
  if(!hasPlane.value)   return;

  if(key === 'untrace') {
    window.measureViewer.setNoTrack()
  }else if(key === 'fallow') {
    window.viewer.trackedEntity = window.viewer.entities.getById(store.uav.ModelIDinMap);
  }
}
let barIsOpen = ref(true);
function openCloseBar() {
  // 获取元素
  let toolbar = document.querySelector('.panel-toolbar989834y34');
  if(toolbar?.classList.contains('open')){  //关闭
    toolbar?.classList.remove('open');
  }
  else {         // 打开
    toolbar?.classList.add('open');
  }
  barIsOpen.value = !barIsOpen.value
}

function handleEditSelect(key) {
  if(key === 'createLine') {  // 绘制航线
   showRouteModal.value = true;
  }
  else if(key === 'marker') { // 标记障碍物
    markerDialog.value?.openDlg()
  }
  else{
    // 转到航线管理页面
		router.push({
			name: 'Test',
		})
  }
}
function handleAnalyseSelect(key) {
  if(key === 'visibility') {
    store.analysisVars.analysisType = 2
    //弹出参数窗口
    spatialAnalyse.value?.openParamsDialog()
  }
  if(key === 'profile') {
    store.analysisVars.analysisType = 1
    //弹出参数窗口
    spatialAnalyse.value?.openParamsDialog()
  }

}

function handleDrawSelect(key) {
  if(key === 'clear') {
    if(window.measureViewer.clearDraw()){
      message.warning('无可清除图形')
    }
  }
  else{
    window.measureViewer.drawGraphics(key)
  }
}

// 测量菜单选中事件
function handleSelect(key) {
  if(key === 'distance') {
    measure();
  }
  else if(key === 'area') {
    measureArea()
  }else if(key === 'clear') {
    measureEnd()
  }
}

async function  handleFile() {
  const [fileHandle] = await window?.showOpenFilePicker({
    types: [
      {
        description: "kml/json",
        accept: {"text/kml": ['.kml', '.kmz', '.json', '.geojson']}
      }
    ]
  })

  // 获取文件File对象
  const file = await fileHandle?.getFile()
  console.group("获取到的文件")
  console.log(fileHandle)
  console.log(file.name)
  if(file.name.toLowerCase().endsWith('kml')||file.name.toLowerCase().endsWith('kmz')){
    window.measureViewer.addKml(file)
  }
  else if(file.name.toLowerCase().endsWith('geojson')||file.name.toLowerCase().endsWith('json')||file.name.toLowerCase().endsWith('topojson')) {
    window.measureViewer.addJson(file)
  }
}

/**
 * 多点距离测量
 */
function measure(){
  window.measureViewer.clearDisEntity()
  window.measureViewer.activate()
}

/**
 * 清除面积测量和多点距离测量
 */
function measureEnd(){
  if(window.measureViewer.vertexEntities.length>0 || window.measureViewer.activeShapePoints.length>0){
    window.measureViewer.deactivate()
    window.measureViewer.stopAreaMeasure()
    window.measureViewer.clearDisEntity()
    window.measureViewer.clearAreaEntity()
    window.measureViewer.viewer.scene.requestRender()
  }else{
    message.warning('无可清除元素')
  }
}

/**
 * 面积测量
 */
function measureArea() {
  window.measureViewer.clearAreaEntity()
  window.measureViewer.activateAreaMeasure();
}

/**
 * 连接websocket
 * @returns {Promise<void>}
 */
async function connectWebSocket() {
  store.webskt.ws = new WebSocket('ws://'+store.webskt.ws_config.address+':'+store.webskt.ws_config.port);
  store.webskt.ws.onopen = function(event){
    console.log("Connection open ...")
    store.webskt.ws.send("hello QT!")
  }

  store.webskt.ws.onmessage = (event) => {
    //收到消息后的处理流程....
    let sktData = JSON.parse(event.data)
    // console.log(sktData);
    frameCount++
    if(sktData.type === 0){
      let ycData = dataProcess_fromQT(sktData)
      if (ycData != null) {
        // 更新遥测数据（飞机位置）
        window.measureViewer.updateDynamicData(ycData)
        lStore.validYCData = true
        // 添加飞机三维图标
        if(!hasPlane.value){
          window.measureViewer.addAirplaneEntity(store.models.fp98, ycData.uavId + ycData.uavType)
          SceneValue.value = 'fallow'
          hasPlane.value = true;
        }
        // 加载和更新碰撞检测图(50帧更新一次)
        if(frameCount>50 && lStore.openDetect){
          emit('resizeMap', detectDivHeight.value)
          showDetection.value = true
          frameCount = 0
          let currentPos = Cartesian3.fromDegrees(ycData.lon, ycData.lat,ycData.alt)
          // 显示飞机当前位置的地表投影点海拔高度 和 飞机高度（折线图）
          new Promise(resolve => {
            // 计算对地高度 m
            groundHeight.value = ycData.alt - getElevation(window.viewer, currentPos)
            // 计算当前点与上一点的距离 米
            if(lastPos===undefined){
              lastPos = currentPos;
            }
            let dis = getDistance(currentPos, lastPos) * 1000
            lastPos = currentPos
            resolve(dis)
          }).then(res=>{
            collisionDetection.value.drawDetection(ycData.alt, res, ycData.alt-groundHeight.value)
          })
          // 当前飞机高度（折线图） 和飞机前方10公里处的地形高度（以飞机当前航向推算）
          let max_dis = 5000
          new Promise(resolve => {
            // 计算前方5公里处的坐标点
            let detectPos = ByDirectionAndLen(currentPos, ycData.heading, max_dis)
            // 计算地形剖面
            collisionDetection.value.drawTerrain(ycData.alt, currentPos, detectPos, max_dis)
            resolve(detectPos)
          })
        }
      }
      else{ //遥测解析错误或无数据
        lStore.validYCData = false
      }
    }
    if(sktData.type === 1){
      let routeData = dataProcess_fromQT_route(sktData)
      if(routeData != null){
        lStore.navi.airlines.push(routeData)
        lStore.navi.currentRouteID = routeData.code
        console.log(routeData)
        window.measureViewer.showAirLine(routeData)
      }

    }
  };
}

/**
 * 将航线信息发送给QT端（每次发送一条航线）
 * @param route 航线，Airline类型
 */
function sendRouteToQT(route){
  if(store.webskt.ws?.readyState == WebSocket.OPEN){
    store.webskt.ws.send(JSON.stringify(route))
  }
}
//关闭动态碰撞检测功能
function shutDownDetec() {
  if(lStore.openDetect){
    emit('resizeMap', -1)
  }else{
    emit('resizeMap', detectDivHeight.value)
  }
  showDetection.value = !showDetection.value;
  lStore.openDetect = !lStore.openDetect

}
/**
 * 关闭websocket连接
 */
function closeWS(){
  if(store.webskt.ws){
    store.webskt.ws.close();
  }
}

function manageLayer(){
  layerManager.value?.open_closeSidebar()
}

/**
 * 绘制航线，目前只绘制任务航线
 * @param routeParams 航线属性
 */
function startDrawRoute(routeParams /*{code: number,isOpen: bool,height: number,routePts: []}*/) {
  showRouteModal.value = false
  let drawLine = new RouteManageViewer(window.viewer, routeParams.isClose, routeParams.height)
  drawLine.start().then(result => {
    console.log(result)
    // result是经纬度坐标数组，需转换为 AirlinePoint数组
    let AirlinePoints = []
		result.forEach((pt,index) => {
			let AirlinePoint = {lon:pt.lon, lat:pt.lat, alt:pt.alt, ch1:routeParams.isClose? 2:0, ch2:0x03, speed:0, nPt:index}
			AirlinePoints.push(AirlinePoint)
		})
		AirlinePoints.at(-1).ch2 = 0x01;
    // 航线加入store
    let aRoute = {
      code: routeParams.code, PtNum: result.length, isClose: routeParams.isClose, name: "", points: AirlinePoints, totalDistance: 0
    }
    useRouteStore().route.push(aRoute)
    // fixme: 航线加入图层管理

  }).catch(reject => {
    message.error(reject)
  })
}
</script>

<template>
  <n-space class="panel-toolbar989834y34">
    <n-row justify-content="space-between">
    <n-tooltip placement="bottom" trigger="hover" >
      <template #trigger>
        <n-button tertiary type="warning" @click="manageLayer">
          <template #icon>
            <n-icon><Layers/></n-icon>
          </template>
        </n-button>
      </template>
      <span> 图层管理 </span>
    </n-tooltip>
    <n-tooltip placement="bottom" trigger="hover">
      <template #trigger>
        <n-button tertiary circle type="warning" @click="handleFile">
          <template #icon>
            <n-icon><DuplicateSharp /></n-icon>
          </template>
        </n-button>
      </template>
      <span> 添加数据 </span>
    </n-tooltip>
    <n-dropdown :options="store.menuOptions.AnalyzeOptions" @select="handleAnalyseSelect">
    <n-button tertiary type="warning">
      <template #icon>
        <n-icon><TerrainSharp/></n-icon>
      </template>
    </n-button>
    </n-dropdown>
    <n-dropdown :options="store.menuOptions.EditOptions" @select="handleEditSelect">
    <n-button tertiary circle type="warning">
    <!--航线绘制-->
      <template #icon>
        <n-icon><CreateOutline/></n-icon>
      </template>
    </n-button>
    </n-dropdown>
    <n-dropdown :options="store.menuOptions.MeasureOptions" @select="handleSelect">
    <n-button tertiary type="warning">
      <template #icon>
      <n-icon><RulerAlt/></n-icon>
      </template>
    </n-button>
    </n-dropdown>
    <n-dropdown :options="store.menuOptions.DrawOptions" @select="handleDrawSelect">
    <n-button tertiary circle type="warning">
      <template #icon>
        <n-icon><DrawPolygon/></n-icon>
      </template>
    </n-button>
    </n-dropdown>
    <n-tooltip placement="bottom" trigger="hover">
      <template #trigger>
        <n-button tertiary type="warning" @click="showModal = true">
          <template #icon>
            <n-icon><Settings/></n-icon>
          </template>
        </n-button>
      </template>
      <span> WebSocket配置 </span>
    </n-tooltip>
    <n-popselect v-model:value="SceneValue" :options="store.menuOptions.sceneOptions"
                 @update:value="handleSceneSelect" size="medium">
      <n-button tertiary circle type="warning">
        <template #icon>
          <n-icon><EyeSharp/></n-icon>
        </template>
      </n-button>
    </n-popselect>
    <n-button tertiary circle type="warning" @click="openCloseBar">
      <template #icon>
        <n-icon v-if="barIsOpen"><ChevronBack/></n-icon>
        <n-icon v-else><ChevronForward/></n-icon>
      </template>
    </n-button>
    </n-row>
  </n-space>
  <n-button id="bt_switch" size="small" :type="showDetection? 'error': 'success'" v-if="lStore.validYCData"
            @click="shutDownDetec" :style="{bottom:'0vh'}">
    {{showDetection? '关闭图表': '显示图表'}}
  </n-button>

  <n-collapse-transition v-show="showDetection">
    <n-flex id="detectionGraph" justify="center"
            :style="{height: detectDivHeight +'vh'}">
      <CollisionDetection ref="collisionDetection" ></CollisionDetection>
    </n-flex>
  </n-collapse-transition>


  <n-modal v-model:show="showModal"
        style="width: 30%"
        :mask-closable="false"
        preset="dialog"
        title="">
    <template #header>
      <div>WebsSocket配置</div>
    </template>
    <div style="margin: 2rem 2rem .5rem 1rem">
      <n-space>
        <n-form ref="formRef" :model="store.webskt.ws_config"
                label-placement="left"
                label-width="auto"
                require-mark-placement="right-hanging">
          <n-form-item label="服务器地址">
            <n-input v-model:value="store.webskt.ws_config.address"  placeholder="127.0.0.1"/>
          </n-form-item>
          <n-form-item label="端口号">
            <n-input-number v-model:value="store.webskt.ws_config.port" placeholder=8000 />
          </n-form-item>
        </n-form>
      </n-space>
      <n-space justify="center">
        <n-button @click="connectWebSocket" type="primary" size="small">开启通信</n-button>
        <n-button @click="closeWS"  type="warning" size="small">关闭通信</n-button>
      </n-space>
    </div>
  </n-modal>

  <SpatialAnalysis ref="spatialAnalyse"></SpatialAnalysis>
  <LayerManager ref="layerManager"></LayerManager>
  <RouteOptions v-model:show="showRouteModal" @routeDraw="startDrawRoute" @cancelDraw="showRouteModal = false"/>
  <MarkerDialog ref="markerDialog"></MarkerDialog>
</template>

<style>
.panel-toolbar989834y34{
  position: absolute;
  top: 10px;
  left: 2px;
  border-radius: 7px;
  background: rgba(21, 21, 21, 0.94);
  transition: left 0.3s;
}

.panel-toolbar989834y34.open{
  position: absolute;
  left: -20rem;
}

#bt_switch{
  position: absolute;
  z-index: 2;
}

#detectionGraph{
  position: absolute;
  bottom: -25vh;
  width: 100vW;
  border-radius: 7px;
  background: rgba(255, 255, 255, 0.8);
}

</style>
