<!--
 * @Author: wrh
 * @Date: 2024-12-09 10:20:29
 * @LastEditors: wrh
 * @LastEditTime: 2025-01-24 11:17:27
-->
<template>
  <div>
    <!-- 工具栏 -->
    <div class="tool-box">
      <div>
        <a-tooltip placement="rightTop">
          <template #title>3D显示</template>
          <a-button @click="display3D">
            <svg-icon icon-class="3d" class-name='custom-class' />
          </a-button>
        </a-tooltip>
      </div>
      <div>
        <a-tooltip placement="rightTop">
          <template #title>图层</template>
          <a-button @click="layersOpen = !layersOpen">
            <svg-icon icon-class="layers" class-name='custom-class' />
          </a-button>
        </a-tooltip>
      </div>
      <div>
        <a-tooltip placement="rightTop">
          <template #title>测距</template>
          <a-button @click="measureDistanceHandle('LineString')">
            <svg-icon icon-class="ruler-blod" class-name='custom-class' />
          </a-button>
        </a-tooltip>
      </div>
      <div>
        <a-tooltip placement="rightTop">
          <template #title>测面</template>
          <a-button @click="measureDistanceHandle('Polygon')">
            <svg-icon icon-class="area-cutom" class-name='custom-class' />
          </a-button>
        </a-tooltip>
      </div>
      <!-- <div>
        <a-tooltip placement="rightTop">
          <template #title>加点</template>
          <a-button>
            <svg-icon icon-class="maps-point" class-name='custom-class' />
          </a-button>
        </a-tooltip>
      </div> -->
      <div>
        <a-tooltip placement="rightTop">
          <template #title>添加数据</template>
          <a-button @click="clickAddDataSource">
            <svg-icon icon-class="plus-bold" class-name='custom-class' />
          </a-button>
        </a-tooltip>
      </div>
      <div>
        <a-tooltip placement="rightTop">
          <template #title>影像解译</template>
          <a-button @click="segmentOpen = !segmentOpen">
            <svg-icon icon-class="seg" class-name='custom-class' />
          </a-button>
        </a-tooltip>
      </div>
    </div>
    <!-- 添加数据框 -->
    <div class="sourceBox" v-if="sourceOpen">
      <div class="header">
        添加数据
        <div class="close" @click="sourceOpen = false">×</div>
      </div>
      <div class="source-main">
        <a-row>
          请选择数据类型：
        </a-row>
        <a-row style="margin-bottom: 10px;">
          <a-space direction="vertical">
            <a-radio-group v-model:value="radioVal" :options="plainOptions" @change="handleChangeRadio" />
          </a-space>
        </a-row>
        <a-row style="margin-bottom: 10px;">
          <a-col :span="6" style="vertical-align: middle;line-height: 32px;">图层名：</a-col>
          <a-col :span="18">
            <a-input v-model:value="layersName" placeholder="请输入图层名" />
          </a-col>
        </a-row>
        <a-row style="margin-bottom: 10px;" class="tip-text">
          {{ tipsText }}
        </a-row>
        <a-row justify="center">
          <a-upload :accept="acceptType" v-model="files" :customRequest="customUpload" multiple @change="handleChange">
            <a-button preIcon="ic:baseline-add" :disabled="layersName == '' ? false : false">
              选择文件
            </a-button>
          </a-upload>
        </a-row>
        <a-row justify="center"><a-col name="progressStatus"></a-col></a-row>
      </div>
    </div>
    <!-- 图层对话框 -->
    <div class="layersBox" v-if="layersOpen">
      <Layers @opentableable="tableIsOpen" @returntableData="getTableData" @returntableName="getTableName" @close="layersOpen = false"></Layers>
    </div>
    <!-- 属性表对话框 -->
    <div class="data-table" v-if="tableOpen">
      <div class="ol-popup-closer" @click="tableOpen = false"></div>
      <dataTable :tableData="tableData" :tableName="tableName"></dataTable>
    </div>
    <!-- 测量框 -->
    <div class="measure-box" v-if="measureEnable == true">
      <el-alert :closable="false" :title="'测量值：' + measureValue" type="warning">
        <el-button type="warning" size="small" @click="removeMeasure">清除图形</el-button>
        <el-button plain size="small" type="warning" @click="measureEnable = false">关闭</el-button>
        <div style="margin-top: 10px;">Tips:测量开始，按ESC可退出测量模式</div>
      </el-alert>
    </div>
    <!-- 影像解译对话框 -->
    <div class="segBox" v-if="segmentOpen">
      <Segment @close="segmentOpen = false"></Segment>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref,getCurrentInstance } from "vue";
import useMapStore from '@/store/modules/maps';
import shp from 'shpjs/dist/shp';
import VectorLayer from 'ol/layer/Vector';
import { Vector as VectorSource } from 'ol/source';
// import KML from 'ol/format/KML';
import { GeoJSON, KML } from 'ol/format';
import { Style, Fill, Stroke, Circle, Text } from 'ol/style';
import { getDxf2GeoJSON, getDxf2Shp, getProcessValue, getGeoJSONFromDxf } from "@/api/map/multidatasource";
import Draw from 'ol/interaction/Draw.js';
import { LineString, Polygon } from 'ol/geom.js';
import { getArea, getLength } from 'ol/sphere.js';
import { unByKey } from 'ol/Observable.js';
// ---------------------------------------------------------------------------------------------------------------------------------
import Layers from "./layers.vue";
import Segment from "./segment.vue";
import dataTable from "./dataTable.vue";
// ---------------------------------------------------------------------------------------------------------------------------------
const {proxy} = getCurrentInstance();
const useOlMap = useMapStore();
const sourceOpen = ref(false);
const layersOpen = ref(false);
const segmentOpen = ref(false);
const tableOpen = ref(false);
const tableData = ref([]);
const tableName = ref("");
const measureEnable = ref(false);
const radioVal = ref("SHP");
const plainOptions = ref(['SHP', 'DXF', 'KML', 'GeoJSON']);
const layersName = ref("");
const files = ref([]);
const fileList = ref([]);
const acceptType = ref(".zip");
const types = ref("");
const tipsText = ref("Tips:请选择包含shp文件的zip");
const measureValue = ref("");
let draw: Draw;
let drawSource: VectorSource;
let drawVector: any = null;
let sketch: any = null;
let listener;

function tableIsOpen(param) {
  tableOpen.value = !param
}
function getTableData(param) {
  tableData.value = param
}
function getTableName(param) {
  tableName.value = param
}
// 控制二三维联动的3D显示
function display3D() {
  let status = window.ol3d.getEnabled();
  let element3D = <HTMLImageElement>document.querySelector('.ol-cesium');
  let element2D = <HTMLImageElement>document.querySelector('.ol-ol');
  let tigger = <HTMLImageElement>document.querySelector('.move-line');
  if (status) {
    window.ol3d.setEnabled(false);
    element2D.style.width = '100%';
    tigger.style.display = 'none';
    element3D.style.flex = '0';
  } else {
    window.ol3d.setEnabled(true);
    element2D.style.width = '50%';
    tigger.style.display = 'block';
    tigger.style.width = '10px';
    element3D.style.flex = '1';
  }
  let logoDom = <HTMLImageElement>document.querySelector('#olCesium .cesium-credit-logoContainer');
  logoDom.style.display = 'none';
}
// 添加数据按钮
function clickAddDataSource() {
  sourceOpen.value = !sourceOpen.value;
  layersName.value = "";
}


const handleChangeRadio = (e) => {
  let val = e.target.value;
  if (val == 'SHP') {
    acceptType.value = ".zip";
    tipsText.value = "Tips:请选择包含shp文件的zip";
  } else if (val == 'GeoJSON') {
    acceptType.value = ".geojson,.json";
    tipsText.value = "";
  } else {
    acceptType.value = "." + val;
    tipsText.value = ""
  }
}

// 自定义上传文件
function customUpload(file) {
  if (radioVal.value == 'SHP') {
    getShp(file);
  } else if (radioVal.value == 'KML') {
    getKml(file);
  } else if (radioVal.value == 'GeoJSON') {
    getGeoJson(file);
  } else if (radioVal.value == 'DXF') {
    getDxf(file);
  }
};
const handleChange = (files) => {
  fileList.value = files.fileList;
}
// 加载Shp文件
function getShp(file) {
  const reader = new FileReader();
  const fileData = file.file;
  reader.readAsArrayBuffer(fileData);
  reader.onload = function (e) {
    shp(e.target?.result).then(geojson => {
      const vectorSource = new VectorSource({
        features: new GeoJSON().readFeatures(geojson),
      });
      let style = new Style({
        image: new Circle({
          fill: new Fill({
            color: 'rgba(255,255,255,0.2)'
          }),
          stroke: new Stroke({
            color: '#3399CC',
            width: 2,
          }),
          radius: 5,
        }),
        fill: new Fill({
          color: 'rgba(0,0,255,0.2)'
        }),
        stroke: new Stroke({
          color:  'rgba(190,232,255,0.8)',
          width: 3
        })
      })
      const vectorLayer = new VectorLayer({
        style: style,
        source: vectorSource
      });
      vectorLayer.title = layersName.value == '' ? file.file.name.replace(".zip", "") : layersName.value;
      useOlMap.$state.olmap?.addLayer(vectorLayer);
      file.onSuccess();
      sourceOpen.value = false;
      useOlMap.$state.olmap?.getView().fit(vectorLayer.getSource()?.getExtent());
    })
  }
}
// 加载KML文件
function getKml(file) {
  debugger
  const f = URL.createObjectURL(file.file);
  let color = 'rgba(' + parseInt(Math.random() * 255) + ',' + parseInt(Math.random() * 255) + ',' + parseInt(Math.random() * 255) + ',0.8)';
  let style = new Style({
    image: new Circle({
      fill: new Fill({
        color: 'rgba(255,255,255,0.8)'
      }),
      stroke: new Stroke({
        color: '#3399CC',
        width: 2,
      }),
      radius: 5,
    }),
    fill: new Fill({
      color: color,
    }),
    stroke: new Stroke({
      color: color,
      width: 3
    })
  })
  const vectorLayer = new VectorLayer({
    style: style,
    source: new VectorSource({
      url: f,
      format: new KML({
        extractStyles: false
      }),
    })
  });

  vectorLayer.title = layersName.value == '' ? file.file.name.replace(".kml", "") : layersName.value;
  useOlMap.$state.olmap?.addLayer(vectorLayer);
  file.onSuccess();
  sourceOpen.value = false;
  setTimeout(() => {
    try {
      useOlMap.$state.olmap?.getView().fit(vectorLayer.getSource()?.getExtent());
    } catch (error) {
      proxy.$modal.msgError('文件有误，加载失败');
    }

  }, 500);
}
// 加载GeoJson格式文件
function getGeoJson(file) {
  const reader = new FileReader();
  const fileData = file.file;
  reader.readAsText(fileData, "utf-8");
  reader.onload = function (e) {
    let geojson = e.target?.result;
    const vectorSource = new VectorSource({
      features: new GeoJSON().readFeatures(geojson),
    });
    const vectorLayer = new VectorLayer({
      style: function (feat) {
        var style = new Style({
          stroke: new Stroke({
            color: getColor(feat.getProperties().Layer),
            width: 2
          }),
          text: new Text({
            text: feat.getProperties().Text,
            font: '10px sans-serif',
            textAlign: "left",
            textBaseline: "middle",
            fill: new Fill({
              color: getColor(feat.getProperties().Layer)
            }),
            placement: "point", //point 则自动计算面的中心k点然后标注  line 则根据面要素的边进行标注
            overflow: false //超出面的部分不显示
          })
        })
        feat.setStyle(style);
      },
      source: vectorSource
    });
    vectorLayer.title = layersName.value == '' ? file.file.name.replace(".geojson", "") : layersName.value;
    useOlMap.$state.olmap?.addLayer(vectorLayer);
    file.onSuccess();
    sourceOpen.value = false;
    setTimeout(() => {
      useOlMap.$state.olmap?.getView().fit(vectorLayer.getSource()?.getExtent());
    }, 500);
  }
}

// 加载dxf格式文件
function getDxf(file) { //有几个文件会进方法几次
  // var timer;
  // clearInterval(timer)
  let formData = new FormData();
  formData.append("file", file.file, file.file.name);  //当前文件存入formData，用于调用
  // let currentfileNum = "0";
  // getProcess()
  // function getProcess() {
  //   timer = setInterval(function () { //隔200毫秒获取进度
  //     getProcessValue().then(res => {
  //       currentfileNum = res.msg.split(",")[1]
  //       document.getElementsByName("progressStatus")[0].textContent = res.msg.split(",")[0]
  //     });
  //   }, 200)
  // }
  // getDxf2GeoJSON(formData).then(() => { //调用，转换格式
  //   clearInterval(timer)
  //   for (let i = 0; i < Number(currentfileNum) + 50; i++) { //遍历范围设置得较大，防止加载不全
  //     getGeoJSONFromDxf({ geoJsonName: formData.get("file")?.name.replace(".dxf", "") + i }).then(res => { //调用，获取单个geojson
  //       if (res.msg != "加载完成") {
  //         let geojson = res.data;
  //         const vectorSource = new VectorSource({
  //           features: new GeoJSON().readFeatures(geojson),
  //         });
  //         const vectorLayer = new VectorLayer({
  //           style: function (feat) {
  //             var style = new Style({
  //               stroke: new Stroke({
  //                 color: feat.getProperties().color,
  //                 width: 2
  //               }),
  //               text: new Text({
  //                 text: feat.getProperties().Text,
  //                 font: '10px sans-serif',
  //                 textAlign: "left",
  //                 textBaseline: "middle",
  //                 fill: new Fill({
  //                   color: feat.getProperties().color
  //                 }),
  //                 placement: "point", //point 则自动计算面的中心k点然后标注  line 则根据面要素的边进行标注
  //                 overflow: false //超出面的部分不显示
  //               })
  //             })
  //             feat.setStyle(style);
  //           },
  //           source: vectorSource
  //         });
  //         vectorLayer.title = layersName.value == '' ? file.file.name.replace(".dxf", "") + i : layersName.value;
  //         useOlMap.$state.olmap?.addLayer(vectorLayer);
  //         file.onSuccess();
  //         sourceOpen.value = false;
  //         setTimeout(() => {
  //           useOlMap.$state.olmap?.getView().fit(vectorLayer.getSource()?.getExtent());
  //         }, 500);
  //       }
  //     })
  //   }
  //   sourceOpen.value = false;
  // })
  getDxf2Shp(formData).then(() => { //调用，转换格式
    // clearInterval(timer)
    // for (let i = 0; i < Number(currentfileNum) + 50; i++) { //遍历范围设置得较大，防止加载不全
    //   getGeoJSONFromDxf({ geoJsonName: formData.get("file")?.name.replace(".dxf", "") + i }).then(res => { //调用，获取单个geojson
    //     if (res.msg != "加载完成") {
    //       let geojson = res.data;
    //       const vectorSource = new VectorSource({
    //         features: new GeoJSON().readFeatures(geojson),
    //       });
    //       const vectorLayer = new VectorLayer({
    //         style: function (feat) {
    //           var style = new Style({
    //             stroke: new Stroke({
    //               color: feat.getProperties().color,
    //               width: 2
    //             }),
    //             text: new Text({
    //               text: feat.getProperties().Text,
    //               font: '10px sans-serif',
    //               textAlign: "left",
    //               textBaseline: "middle",
    //               fill: new Fill({
    //                 color: feat.getProperties().color
    //               }),
    //               placement: "point", //point 则自动计算面的中心k点然后标注  line 则根据面要素的边进行标注
    //               overflow: false //超出面的部分不显示
    //             })
    //           })
    //           feat.setStyle(style);
    //         },
    //         source: vectorSource
    //       });
    //       vectorLayer.title = layersName.value == '' ? file.file.name.replace(".dxf", "") + i : layersName.value;
    //       useOlMap.$state.olmap?.addLayer(vectorLayer);
    //       file.onSuccess();
    //       sourceOpen.value = false;
    //       setTimeout(() => {
    //         useOlMap.$state.olmap?.getView().fit(vectorLayer.getSource()?.getExtent());
    //       }, 500);
    //     }
    //   })
    // }
    // sourceOpen.value = false;
  })
}

function getColor(layer) {
  let color = "#FF0000";
  if (!isNaN(parseInt(layer))) {
    let layerNum = parseInt(layer);
    if (layerNum < 4000)
      color = "#FF0000"; //1
    else if (layerNum < 5000)
      color = "#00FFFF"; //4
    else if (layerNum < 5300)
      color = "#FF0000"; //1
    else if (layerNum < 5500)
      color = "#0000FF"; //5
    else if (layerNum < 6000)
      color = "#FF0000"; //1
    else if (layerNum < 6400)
      color = "#0000FF"; //5
    else if (layerNum < 6740)
      color = "#FF0000"; //1
    else if (layerNum < 6742)
      color = "#FFFFFF"; //7
    else if (layerNum < 6743)
      color = "#FFFF00"; //2
    else if (layerNum < 6752)
      color = "#FFFFFF"; //7
    else if (layerNum < 6753)
      color = "#FFFF00"; //2
    else if (layerNum < 8000)
      color = "#FF0000"; //1
    else if (layerNum < 8111)
      color = "#FFFFFF"; //7
    else if (layerNum < 8121)
      color = "#FFFF00"; //2
    else if (layerNum < 8122)
      color = "#FF0000"; //1
    else if (layerNum < 8131)
      color = "#FFFFFF"; //7
    else if (layerNum < 8300)
      color = "#FFFF00"; //2
    else if (layerNum < 8700)
      color = "#FF0000"; //1
    else if (layerNum < 9612)
      color = "#00FF00"; //3
    else if (layerNum < 9613)
      color = "#00FFFF"; //4
    else if (layerNum < 9614)
      color = "#00FF00"; //3
    else if (layerNum < 9801)
      color = "#FF0000"; //1
    else if (layerNum < 10000)
      color = "#00FF00"; //3
  }
  return color;
}

// 测量按钮事件
function measureDistanceHandle(type) {
  if (draw) {
    draw.setActive(false);
    draw.finishDrawing();
    useOlMap.$state.olmap.removeInteraction(draw);
  }
  measureEnable.value = true;
  measureValue.value = "";
  if (type == "LineString") {
    types.value = 'LineString';
    addMeasureInteraction();
  } else {
    types.value = 'Polygon';
    addMeasureInteraction();
  }
}
// 添加测量交互
function addMeasureInteraction() {
  let maps = useOlMap.$state.olmap;
  drawSource = new VectorSource();
  drawVector = new VectorLayer({
    source: drawSource,
    style: new Style({
      fill: new Fill({
        color: "rgba(255, 255, 255, 0.2)",
      }),
      stroke: new Stroke({
        color: "#ffcc33",
        width: 2,
      }),
      image: new Circle({
        radius: 7,
        fill: new Fill({
          color: "#ffcc33",
        }),
      }),
    }),
  });
  drawVector.title = "测距图层" + parseInt(Math.random() * (10 - 1 + 1) + 1)
  draw && maps!.removeInteraction(draw);
  draw = new Draw({
    source: drawVector.getSource(),
    type: types.value,
    stopClick: true,
  });

  drawHandler();
  maps.addInteraction(draw);
}

function drawHandler() {
  draw.on('drawstart', (evt: any) => {
    sketch = evt.feature;
    listener = sketch.getGeometry().on("change", (evt: any) => {
      let output;
      const geom = evt.target;
      if (geom instanceof LineString) {
        output = formatLength(geom);
      } else if (geom instanceof Polygon) {
        output = formatArea(geom);
      }
      measureValue.value = output;
      drawSource.clear();
    })
  });
  draw.on('drawend', (evt: any) => {
    let maps = useOlMap.$state.olmap;
    sketch = null;
    unByKey(listener);
    maps.addLayer(drawVector);
    // maps.addInteraction(draw);
  });
  document.onkeydown = function (event) {
    let maps = useOlMap.$state.olmap;
    if (event.key == "Escape") {
      draw.setActive(false)
      if (draw) {
        sketch = null;
        unByKey(listener);
        draw.finishDrawing();
        maps.removeInteraction(draw);
        draw = null;
      }
    }
    else if (event.key == "z" && event.ctrlKey) {
      draw.removeLastPoint()
    }
  }
}
function removeMeasure() {
  let maps = useOlMap.$state.olmap;
  let layers = maps.getLayers().getArray();
  for (let layer of layers) {
    if (layer instanceof VectorLayer) {
      if (layer.title.indexOf('测距图层') != -1) {
        maps.removeLayer(layer);
      }
    }

  }
}
const formatLength = (line: any) => {
  let maps = useOlMap.$state.olmap;
  const sourceProj = maps.getView().getProjection(); //获取投影坐标系
  var length = getLength(line, { projection: sourceProj });
  var output;
  if (length > 100) {
    output = Math.round((length / 1000) * 100) / 100 + " " + "km";
  } else {
    output = Math.round(length * 100) / 100 + " " + "m";
  }
  return output;
}
const formatArea = (polygon: any) => {
  let maps = useOlMap.$state.olmap;
  const sourceProj = maps.getView().getProjection(); //获取投影坐标系
  const geom = polygon.clone().transform(sourceProj, "EPSG:3857");
  const area = getArea(geom);
  let output;
  if (area > 10000) {
    output =
      Math.round((area / 1000000) * 100) / 100 + " " + "km²";
  } else {
    output = Math.round(area * 100) / 100 + " " + "m²";
  }
  return output;
}
</script>

<style scoped lang="scss">
.tool-box {
  // display: flex;
  /* width: 400px; */
  position: absolute;
  top: 60px;
  left: 10px;
  z-index: 10;
}

.custom-class {
  font-size: 22px;
}

.sourceBox {
  position: absolute;
  top: 150px;
  left: 50%;
  transform: translate(-50%, 0%);
  width: 330px;
  background-color: #fff;
  z-index: 10;

  .header {
    text-align: center;
    line-height: 40px;
    position: relative;
    background-color: #151515;
    color: #fff;

    .close {
      position: absolute;
      top: -3px;
      right: 10px;
      cursor: pointer;
      font-size: 18px;
    }
  }

  .source-main {
    padding: 8px;
  }
}

.layersBox {
  position: absolute;
  top: 60px;
  left: 70px;
  background-color: #fff;
  border-radius: 4px;
  width: 200px;
  height: 500px;
  z-index: 10;
}

.segBox {
  position: absolute;
  top: 50px;
  left: 50%;
  transform: translate(-50%, 0%);
  width: 1000px;
  background-color: #fff;
  z-index: 10;

  .header {
    text-align: center;
    line-height: 40px;
    position: relative;
    background-color: #151515;
    color: #fff;

    .close {
      position: absolute;
      top: -3px;
      right: 10px;
      cursor: pointer;
      font-size: 18px;
    }
  }
}

.data-table {
  position: absolute;
  bottom: 10px;
  top: 70%;
  left: 10%;
  background-color: #fff;
  border-radius: 4px;
  width: 80%;
  z-index: 10;
}

.ol-popup-closer {
  text-decoration: none;
  position: absolute;
  top: -6px;
  right: 8px;
}

.ol-popup-closer:after {
  content: "×";
  color: #151515;
  font-weight: bold;
  font-size: 22px;
}

.ol-popup-closer:hover:after {
  color: #40a9ff;
}

.measure-box {
  position: absolute;
  top: 30px;
  left: 50%;
  transform: translate(-50%, 0);
  color: #fff;
  z-index: 22;
}
</style>