<!--
 * @Descripttion: 
 * @version: 
 * @Author: ysh
 * @Date: 2023-06-12 14:20:42
 * @LastEditors: wrh
 * @LastEditTime: 2024-08-15 17:41:19
-->
<template>
  <div class="dialog_content">
    <div class="header">
      添加数据源
      <div class="close" @click="cancelDataSource">×</div>
    </div>
    <div class="main">
      <el-form label-width="90px">
        <el-form-item label="文件类型">
          <el-select v-model="filesType" class="m-2" placeholder="请选择文件类型" @change="handleSelectChange">
            <el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value" />
          </el-select>
        </el-form-item>
        <el-form-item label="选择文件夹">
          <el-input v-model="pathString" placeholder="请选择文件路径" :disabled="isDisabled">
            <template #append>
              <el-button icon="Folder" @click="handleOpenDialog" :disabled="isDisabled"></el-button>
            </template>
          </el-input>
        </el-form-item>
        <el-form-item label="选取坐标" v-if="selectPositionShow">
          <el-input v-model="locationString" placeholder="格式:经度,纬度,高度(小写逗号)" :disabled="isSelectDisabled">
            <template #append>
              <el-button icon="AddLocation" :disabled="isSelectDisabled" @click="handleSelectPosition"></el-button>
            </template>
          </el-input>
        </el-form-item>
        <input hidden type="file" id="chooseFile" name="chooseFile" :accept="returnFileType(filesType)"
          @change="handleInputChange">
      </el-form>
      <el-row justify="center" style="margin-bottom: 10px;">
        <el-button type="primary" @click="confirmAddDataSource">添加</el-button>
        <el-button @click="cancelDataSource">取消</el-button>
      </el-row>
    </div>
    <!-- 文件目录对话框 -->
    <el-dialog v-model="openFileDialog" title="选择文件路径" width="480px" :close-on-click-modal="false" :align-center="true">
      <Folder :folderList="folderList" :pathList="pathList" @changePath="changePath" @changeBackPath="changeBackPath"
        @handleConfirm="confirmPath" @cancel="openFileDialog = false"></Folder>
    </el-dialog>

  </div>
</template>

<script setup lang="ts" name="Datasource">
import { ref, reactive, getCurrentInstance } from 'vue';
import { getPath, folderMapping, uploadFile, getDxf2GeoJSON, getProcessValue, getGeoJSONFromDxf } from '@/api/map/multidatasource';
import useMapStore from '@/store/modules/maps';
import Folder from './folder.vue';
import shp from 'shpjs/dist/shp';
import { styleType } from 'element-plus/es/components/table-v2/src/common';
// --------------------------------------------------------------------------------------
const { proxy } = getCurrentInstance();
const openFileDialog = ref<Boolean>(false);
const folderList = ref<String[]>([]);
const pathList = ref<String[]>([]);
const pathString = ref<String>("");
const filesType = ref<String>("");
const isDisabled = ref<Boolean>(true);
const files = ref<any>(null);
const selectPositionShow = ref<Boolean>(false);
const isSelectDisabled = ref<Boolean>(false);
const locationString = ref<String>("");
const getCoordinateEntity = ref<any>();
const chooseEntity = reactive({
  getCoordinateEntity: null,
  labelEntity: null
})
const options = [
  {
    value: '倾斜模型',
    label: '倾斜模型',
  },
  {
    value: '点云',
    label: '点云',
  },
  {
    value: '影像',
    label: '影像',
  },
  {
    value: '地形',
    label: '地形',
  },
  {
    value: 'DXF',
    label: 'DXF',
  },
  {
    value: 'KML',
    label: 'KML',
  },
  {
    value: 'GeoJSON',
    label: 'GeoJSON',
  },
  {
    value: 'GLB',
    label: 'GLB',
  },
  {
    value: 'glTF',
    label: 'glTF',
  },
  {
    value: 'SHP',
    label: 'SHP',
  },
  // {
  //   value: 'obj',
  //   label: 'obj',
  // },
]
let ce = useMapStore().$state.cesium;
let vi = useMapStore().$state.viewer;



// --------------------------------------------------------------------------------------
// 选择文件
function handleInputChange(e) {
  const f = document.getElementById('chooseFile');
  files.value = e.target.files[0];
  pathString.value = files.value.name;
}

// 返回文件类型
function returnFileType(filesType) {
  if (filesType == 'GeoJSON')
    filesType = '.geojson,.json'
  else if (filesType == 'SHP')
    filesType = '.zip'
  else
    filesType = '.' + filesType;
  return filesType;
}

//确认添加数据
function confirmAddDataSource() {
  if (filesType.value == "") {
    proxy.$modal.msgError(`请选择文件类型`);
    return
  } else if (filesType.value == '倾斜模型' || filesType.value == '点云') {
    if (pathString.value.includes('.json')) {
      let arr = pathString.value.split('/');
      arr.length = arr.length - 1;
      pathString.value = arr.join('/');
    }
    folderMapping({ folderName: pathString.value }).then(res => {
      if (res.code == 200) {
        //为了适应linux，linux配置nginx前端监听接口6112，tileset发布在6111，两个不能相同；windows可以都是6111
        add3DTileset(res.msg.replace(":6111/", ":" + window.location.port + "/resource/") + "/tileset.json",
          filesType.value + " " + pathString.value.split("/")[pathString.value.split("/").length - 1],
          pathString.value)
        // add3DTileset('http://127.0.0.1:8788/model/tileset.json', '','');


      }
    })
  } else if (filesType.value == 'DXF') {
    addDxfDataSource(files.value);
  } else if (filesType.value == 'KML') {
    addKmlDataSource(files.value);
    // let formData = new FormData();
    // formData.append("file", files.value, files.value.name);
    // uploadFile(formData)
  } else if (filesType.value == 'GeoJSON') {
    addGeoJsonDataSource(files.value);
  } else if (filesType.value == 'SHP') {
    addShpDataSource(files.value);
  } else if (filesType.value == '影像') {
    folderMapping({ folderName: pathString.value }).then(res => {
      if (res.code == 200) {
        let imageryProvider = new ce.UrlTemplateImageryProvider({
          url: res.msg.replace(":6111/", ":" + window.location.port + "/resource/") + '/{z}/{x}/{y}.png',
          maximumLevel: 22,
          credit: "本地影像"
        });
        vi.imageryLayers.addImageryProvider(imageryProvider);
      }
    })
  } else if (filesType.value == 'glTF' || filesType.value == 'GLB') {
    if (pathString.value == "") {
      proxy.$modal.msgError(`请选择gltf数据`);
      return
    }
    if (locationString.value == "") {
      proxy.$modal.msgError(`请选择模型要加载的位置`);
      return
    }
    addEntitysSource(files.value);
    removeCesiumHandler();
  } else if (filesType.value == '地形') {
    folderMapping({ folderName: pathString.value }).then(res => {
      if (res.code == 200) {
        let terrainProvider = new ce.CesiumTerrainProvider({
          url: res.msg.replace(":6111/", ":" + window.location.port + "/resource/"),
          maximumLevel: 15,
          credit: "本地地形"
        });
        vi.terrainProvider = terrainProvider;
      }
    })
  }
  cancelDataSource();
}
// 取消添加数据
function cancelDataSource() {
  proxy.$emit('cancel');

  removeCesiumHandler();

}
function handleSelectChange() {
  if (filesType.value == "") {
    isDisabled.value = true;
  } else {
    isDisabled.value = false;
  }
  if (filesType.value == 'glTF' || filesType.value == 'GLB') {
    selectPositionShow.value = true;
  }

}
// 点击打开文件目录对话框时
function handleOpenDialog() {
  if (filesType.value == 'DXF' || filesType.value == 'KML' || filesType.value == 'GeoJSON' || filesType.value == 'GLB' || filesType.value == 'glTF' || filesType.value == 'SHP') {
    let file = document.getElementById('chooseFile');
    file.click();
  } else if (filesType.value == '倾斜模型' || filesType.value == '影像' || filesType.value == '点云' || filesType.value == '地形') {
    openFileDialog.value = true;
    pathList.value = [];
    let pathName = " ";
    getPath({ pathName: pathName }).then(res => {
      if (res.code == 200) {
        folderList.value = res.data.folderList;
      }
    })
  }

}

// 当路径改变时，重新请求新的目录列表
function changePath(val: String[]) {
  for (let v of val) {
    if (v != "") {
      pathList.value.push(v);
    }
  }
  let pathName;
  if (pathList.value.length == 0) {
    pathName = " ";
  } else if (pathList.value.length == 1) {
    pathName = pathList.value[0] + '/';
  }
  else {
    pathName = pathList.value.join('/');
  }
  getPathByName(pathName);
}
// 回退路径事件
function changeBackPath(val) {
  let pathName;
  pathList.value = val;
  if (pathList.value.length == 0) {
    pathName = " ";
  } else if (pathList.value.length == 1) {
    pathName = " ";
  }
  else {
    pathName = pathList.value.join('/');
  }
  getPathByName(pathName);
}

// 根据路径名查询目录
function getPathByName(pathName) {
  getPath({ pathName: pathName }).then(res => {
    if (res.code == 200) {
      let forlist = res.data.folderList;
      let list: Array<String> = [];
      if (pathName == " ") {
        folderList.value = forlist;
        pathList.value = [];
      } else {
        for (let f of forlist) {
          f = f.includes("\\") ? f.split('\\') : f.split('/');
          f = f[f.length - 1];
          list.push(f);
        }
        folderList.value = list;
      }
    }
  })
}
// 当点击确认路径按钮时
function confirmPath() {
  pathString.value = pathList.value.join('\/');
  openFileDialog.value = false;
}
// 加载3DTileset
function add3DTileset(url, featureIdLabel, instanceFeatureIdLabel) {
  let tileset = new ce.Cesium3DTileset({
    url: url,
    featureIdLabel: featureIdLabel,
    instanceFeatureIdLabel: instanceFeatureIdLabel,
    skipLevelOfDetail: false,
    skipLevels: 0,
  });
  // 异步加载模型
  tileset.readyPromise.then(function (model) {
    vi.scene.primitives.add(model);
    let center = model.boundingSphere.center;
    vi.zoomTo(model, new ce.HeadingPitchRange(
      0.0,
      -0.5
    ));
    add3DtilesetHandler()
  })

}

function add3DtilesetHandler() {
  let handler = new ce.ScreenSpaceEventHandler(vi.scene.canvas);
  handler.setInputAction(function (e) {
    const pick = vi.scene.pick(e.position);
    if (!ce.defined(pick)) { vi.scene.screenSpaceCameraController.enableRotate = true; return; };// 如果点击空白区域，则不往下执行
    if (pick.primitive) {
      useMapStore().setTilesetObj(pick.primitive);
    } else {
      return
    }

  }, ce.ScreenSpaceEventType.LEFT_DOWN);
}

// 加载Dxf
function addDxfDataSource(url) {
  var timer;
  clearInterval(timer)
  let formData = new FormData();
  formData.append("file", url, url.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(() => { //调用，转换格式
    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;
          addGeoJsonDataSource(new Blob([geojson], { type: 'application/json' }))
        }
      })
    }
  })
}
// 加载Kml
function addKmlDataSource(url) {
  const options = {
    camera: vi.scene.camera,
    canvas: vi.scene.canvas,
    // 默认贴地
    clampToGround: true,
  };
  ce.KmlDataSource.load(url, options).then(kml => {
    try {
      kml.name = "kml " + url.name.split(".")[0]
      vi.dataSources.add(kml);
      vi.flyTo(kml)
    } catch (error) {
      proxy.$modal.msgError(`文件加载有误，请检查文件格式是否正确`);
    }
  });
}
// 加载geojson
function addGeoJsonDataSource(url) {
  let jsonData = URL.createObjectURL(url);
  ce.GeoJsonDataSource.load(jsonData, {
    markerSize: 1,
    stroke: new ce.Color.fromCssColorString("#ffffff"),
    fill: new ce.Color.fromCssColorString("#ffffff").withAlpha(0.1),
    clampToGround: true
  }).then(geojson => {
    geojson.name = url.name != null ? "GeoJSON " + url.name.split(".")[0] : "DXF"
    vi.dataSources.add(geojson);
    vi.flyTo(geojson)
  });
}
// 加载shp
function addShpDataSource(url) {
  const reader = new FileReader();
  reader.readAsArrayBuffer(url);
  reader.onload = function (e) {
    shp(e.target?.result).then(jsonData => {
      ce.GeoJsonDataSource.load(jsonData, {
        stroke: new ce.Color.fromCssColorString("#ffffff"),
        fill: new ce.Color.fromCssColorString("#ffffff").withAlpha(0.1),
        clampToGround: true
      }).then(geojson => {
        geojson.name = "SHP " + url.name.split(".")[0]
        vi.dataSources.add(geojson);
        vi.flyTo(geojson)
      })
    });
  }
  let jsonData = URL.createObjectURL(url);
  ce.GeoJsonDataSource.load(jsonData).then(geojson => {
    geojson.name = "GeoJSON " + url.name.split(".")[0]
    vi.dataSources.add(geojson);
    vi.flyTo(geojson)
  }, { clampToGround: true });
}

function addEntitysSource(url) {
  if (locationString.value.includes(',')) {
    let p = locationString.value.split(',');
    let lng = Number(p[0]);
    let lat = Number(p[1]);
    let height = Number(p[2]);
    let dataUrl = URL.createObjectURL(url);
    // const position = ce.Cartesian3.fromDegrees(
    //   lng,
    //   lat,
    //   height
    // );
    // let model = vi.entities.add({
    //   model: {
    //     uri: dataUrl,
    //   },
    //   position: position
    // })    
    // vi.flyTo(model);
    let position = ce.Cartesian3.fromDegrees(lng, lat, height);
    let m = ce.Transforms.eastNorthUpToFixedFrame(position);
    let model = vi.scene.primitives.add(
      ce.Model.fromGltf({ url: dataUrl, modelMatrix: m })
    )
    model.readyPromise
      .then(function () {
        var boundingSphere = model.boundingSphere
        vi.camera.viewBoundingSphere(boundingSphere, new ce.HeadingPitchRange(0.0, -0.5, boundingSphere.radius))
        vi.camera.lookAtTransform(ce.Matrix4.IDENTITY)
      })
  } else {
    proxy.$modal.msgError(`位置格式不正确，应为经度,纬度,高程（英文逗号）`);
  }
}

function handleSelectPosition() {
  proxy.$modal.msgWarning(`开始拾取坐标，双击获取`);
  document.querySelector('body').style.cursor = 'crosshair';
  // vi.screenSpaceEventHandler.setInputAction(movement => {
  //   // console.log(move);
  //   let pickedFeatureStart = vi.scene.pick(movement.startPosition);
  //   let pickedObject = vi.scene.pick(movement.endPosition);
  //   let cartesian = vi.scene.pickPosition(movement.startPosition);
  //   if (ce.defined(chooseEntity.labelEntity)) {
  //     chooseEntity.labelEntity.position = cartesian;
  //   } else {
  //     let labelEntity = vi.entities.add({
  //       label: {
  //         text: '双击选取坐标',
  //         show: true,
  //         showBackground: true,
  //         font: '14px monospace',
  //         fillColor: new ce.Color(255, 255, 255, 1),
  //         backgroundPadding: new ce.Cartesian2(10, 10),
  //         pixelOffset: new ce.Cartesian2(80, 30),
  //         backgroundColor: new ce.Color(0.165, 0.165, 0.165, 0.9),
  //         disableDepthTestDistance: Number.POSITIVE_INFINITY, //不开启深度检测
  //         horizontalOrigin: ce.HorizontalOrigin.CENTER,
  //         verticalOrigin: ce.VerticalOrigin.TOP
  //       }
  //     })
  //     labelEntity.position = cartesian;
  //     chooseEntity.labelEntity = labelEntity;
  //   }
  // }, ce.ScreenSpaceEventType.MOUSE_MOVE)
  vi.screenSpaceEventHandler.setInputAction(function (click) {
    let ellipsoid = vi.scene.globe.ellipsoid;
    let earthPosition = vi.camera.pickEllipsoid(click.position, ellipsoid);
    let cartographic = ellipsoid.cartesianToCartographic(earthPosition);
    let longtitude = ce.Math.toDegrees(cartographic.longitude);
    let latitude = ce.Math.toDegrees(cartographic.latitude);
    let height;
    if (vi.terrainProvider instanceof ce.CesiumTerrainProvider) {
      let cartographics = [ce.Cartographic.fromDegrees(longtitude, latitude)];
      ce.sampleTerrainMostDetailed(vi.terrainProvider, cartographics).then(
        updatedPositions => {
          height = updatedPositions[0].height;
          locationString.value = Number(longtitude).toFixed(5) + ',' + Number(latitude).toFixed(5) + ',' + parseInt(height);
        }
      )
    } else {
      height = cartographic.height;
    }
    if (ce.defined(chooseEntity.getCoordinateEntity)) {
      chooseEntity.getCoordinateEntity.position = earthPosition;
      locationString.value = Number(longtitude).toFixed(5) + ',' + Number(latitude).toFixed(5) + ',' + parseInt(height);
    } else {
      let entity = vi.entities.add({
        id: "getCoordinate",
        // position: earthPosition,
        position: ce.Cartesian3.fromDegrees(longtitude, latitude),
        billboard: {
          image: 'src/assets/images/map/location.png',
          heightReference: ce.HeightReference.CLAMP_TO_GROUND,
          disableDepthTestDistance: Number.MAX_VALUE, //不开启深度检测
          width: 32,
          height: 32,
        }
      });
      chooseEntity.getCoordinateEntity = entity;
      locationString.value = Number(longtitude).toFixed(5) + ',' + Number(latitude).toFixed(5) + ',' + parseInt(height);
    }
  }, ce.ScreenSpaceEventType.LEFT_DOUBLE_CLICK);
}

function removeCesiumHandler() {
  vi.screenSpaceEventHandler.removeInputAction(ce.ScreenSpaceEventType.LEFT_DOUBLE_CLICK);
  vi.screenSpaceEventHandler.removeInputAction(ce.ScreenSpaceEventType.MOUSE_MOVE);
  if (ce.defined(chooseEntity.getCoordinateEntity)) {
    vi.entities.remove(chooseEntity.getCoordinateEntity);
    vi.entities.remove(chooseEntity.labelEntity);
  }
}
</script>

<style scoped lang="scss">
.header {
  text-align: center;
  line-height: 40px;
  font-size: 18px;
  position: relative;
  color: #fff;

  .close {
    position: absolute;
    right: 10px;
    top: -5px;
    font-size: 25px;
    color: #fff;
    cursor: pointer;
  }

  .close:hover {
    color: #ff9a00;
  }
}

.main {
  color: #fff !important;
  padding: 15px 15px 5px;
}

.dialog_content {
  position: relative;
  cursor: default;
}

:deep(.el-form-item__label) {
  color: #fff;
}

:deep(.el-input__inner) {
  color: #606266;
}
</style>