<!--
 * @Descripttion: 
 * @version: 
 * @Author: ysh
 * @Date: 2023-06-07 15:52:06
 * @LastEditors: wrh
 * @LastEditTime: 2024-08-15 14:28:41
-->
<template>
  <div class="maps-container">
    <!-- 二维三维切换按钮 -->
    <div class="switch-box">
      <el-switch style="color: #fff;" v-model="switchbtn" size="large" active-text="3D" inactive-text="2D"
        @change="swicthFun" />
    </div>
    <!-- 三维Cesium -->
    <vc-viewer ref="vcViewer" @ready="onCesiumReady" :showCredit="false" :selectionIndicator="false"
      :fullscreenButton="true" :infoBox="false" :scene-mode-picker="true"
      style="position:absolute;width:100vw;height:100%;">
      <CesiumIndex :workspaceShow="workspaceShow" @isOpenWorkSpace="isOpenWorkSpace"></CesiumIndex>
    </vc-viewer>

    <!-- 二维Openlayers -->
    <div class="ol-3d" ref="splitPane">
      <div id="olContainer" class="ol-ol">
        <olIndex></olIndex>
      </div>
      <div class="move-line" @mousedown="tiggerMouseDown"></div>
      <div id="olCesium" class="ol-cesium"></div>
    </div>

    <!-- 鼠标移动时，坐标显示 -->
    <div class="custom-mouse-position" id="mouse-position" v-show="mouseShow"></div>
    <!-- 比例尺 -->
    <div class="scaleBar" id="scaleBar" v-show="mouseShow"></div>
    <!-- ol弹出框 -->
    <transition-group appear name="animate__animated animate__bounce" enter-active-class="animate__fadeInRight"
      leave-active-class="animate__fadeOutRight">
      <div id="popup" class="ol-popup" :key="1" v-if="popShow">
        <a href="#" id="popup-closer" class="ol-popup-closer" @click="closePopup"></a>
        <div id="popup-content">
          <Popup :selectFeatures="selectFeatures"></Popup>
        </div>
      </div>
    </transition-group>
  </div>
</template>

<script setup lang="ts">
import 'ol/ol.css';
import 'vue-cesium/dist/index.css';
import { Map, View } from 'ol'
import XYZ from "ol/source/XYZ";
import OLCesium from 'ol-cesium';
import TileLayer from 'ol/layer/Tile';
import VectorLayer from 'ol/layer/Vector';
import LayerGroup from 'ol/layer/Group';
import { toStringXY } from 'ol/coordinate';
import { Vector as VectorSource } from 'ol/source';
import { GeoJSON, KML, GPX, IGC, TopoJSON } from 'ol/format';
import { Style, Fill, Stroke, Icon, Circle, Text } from 'ol/style';
import { MousePosition, ScaleLine, defaults as defaultControls } from 'ol/control';
import { DragAndDrop, Select, defaults as defaultInteractions } from 'ol/interaction';
// ----------------------------------------------------------------------------------------------------------
import useMapStore from '@/store/modules/maps';
import olIndex from './components/ol/olIndex.vue';
import Popup from './components/ol/popup.vue';
import CesiumIndex from './components/cesium/ceisumIndex.vue'
import { onMounted, onBeforeUnmount, ref, reactive, getCurrentInstance, ComponentInternalInstance } from "vue";
// ----------------------------------------------------------------------------------------------------------
const proxy = getCurrentInstance() as ComponentInternalInstance;
const switchbtn = ref<Boolean>(false);
const state = reactive({
  element2D: <HTMLImageElement>{},
  element3D: <HTMLImageElement>{},
  element2D3D: <HTMLImageElement>{},
  camera: {},
});
const dragAndDropInteraction = new DragAndDrop({
  formatConstructors: [GPX, GeoJSON, IGC, KML, TopoJSON],
});
const popShow = ref<Boolean>(false);
const mouseShow = ref<Boolean>(true);
const workspaceShow = ref<Boolean>(false);
const selectFeatures = ref<Object>();
const triggerLeftOffset = ref(0); //鼠标距滑动器左(顶)侧偏移量
const triggerLength = ref(12) // 滑块的宽度
let control: MousePosition;
// let layerGroup: LayerGroup;
let select: Select;
let selected = null;
// 初始化二三维
function init2Dand3D() {
  control = new MousePosition({
    coordinateFormat: formatCoordinate(4),
    projection: 'EPSG:4326',
    className: 'custom-mouse-position',
    target: document.getElementById('mouse-position')!,
  });
  let scaleBox = new ScaleLine({
    units: 'metric',
    target: <HTMLImageElement>document.querySelector('#scaleBar')
  })
  const olMap = new Map({
    target: "olContainer",
    controls: defaultControls().extend([control, scaleBox]),
    interactions: defaultInteractions().extend([dragAndDropInteraction]),
    layers: [
      new TileLayer({//影像
        source: new XYZ({
          url: 'https://t0.tianditu.gov.cn/DataServer?T=img_w&x={x}&y={y}&l={z}&tk=d6539c1747bf5296bfe35b02151d761a',
        }),
        properties: {
          name: '天地图',
          key: '0-0-0'
        }
      }),
      new TileLayer({//影像
        source: new XYZ({
          url: "https://tiles1.geovisearth.com/base/v1/img/{z}/{x}/{y}" //中科星图 https://tiles1.geovisearth.com/base/v1/cia/{z}/{x}/{y}?format=png&tmsIds=w&token=9b56a7bcb2f51c939753bc066fa6d0e7b7f55cfbf1939fa9e04f53050f4154b9
        }),
        properties: {
          name: '中科星图',
          key: '0-0-1'
        }
      }),
      new TileLayer({//影像
        source: new XYZ({
          url: "https://webst02.is.autonavi.com/appmaptile?style=6&x={x}&y={y}&z={z}"
        }),
        properties: {
          name: '高德',
          key: '0-0-2'
        }
      }),
      new TileLayer({//影像
        source: new XYZ({
          url: "http://mt{1,2,3,0}.google.cn/vt/lyrs=s@142&hl=zh-CN&gl=cn&x=[x]&y=[y]&z=[z]&s=Galil"
        }),
        properties: {
          name: '谷歌',
          key: '0-0-3'
        }
      }),
      new TileLayer({//标注
        source: new XYZ({
          // url: 'http://t4.tianditu.com/DataServer?T=cva_c&tk=81b9a9cf3e4be1df181e7bf54c5949fc&x={x}&y={y}&l={z}',
          url: "http://webst02.is.autonavi.com/appmaptile?x={x}&y={y}&z={z}&lang=zh_cn&size=1&scale=1&style=8",
        }),
        properties: {
          name: '标注图层',
          key: '0-1'
        }
      }),
    ],
    view: new View({
      projection: "EPSG:4326",    //使用这个坐标系
      center: [91.876, 29.97],  //直孔
      zoom: 13
    })
  });
  // layerGroup = new LayerGroup();
  // layerGroup.setProperties({
  //   name: '拖拽图层'
  // });
  // 拖拽数据直接加载
  dragAndDropInteraction.on('addfeatures', function (event) {
    const vectorSource = new VectorSource({
      features: event.features,
    });
    let vectorLayer = new VectorLayer({
      source: vectorSource,
    });
    vectorLayer.title = event.file.name.split(".")[0]
    olMap.addLayer(vectorLayer);
    // let len = layerGroup.getLayers().getArray().length;
    // layerGroup.getLayers().insertAt(len, vectorLayer);
    // let layersss = new LayerGroup();
    // layersss.setProperties({ name: '测试' })
    // try {
    //   olMap.addLayer(layerGroup);
    //   olMap.addLayer(layersss);
    // } catch {

    // }
    olMap.getView().fit(vectorSource.getExtent());
  });
  useMapStore().setOlmap(olMap);
  changeSelectInteraction();
  selectFeatureByHover();
  // 设置ol-cesium的二三维联动
  state.element2D = <HTMLImageElement>document.getElementById("olContainer");
  state.element3D = <HTMLImageElement>document.getElementById("cesiumContainer");
  state.element2D3D = <HTMLImageElement>document.getElementById("olCesium");
  // state.camera = new olcsCamera(
  //   window.viewer.scene,
  //   olMap
  // );
  const ol3d = new OLCesium({ map: olMap, target: 'olCesium' }); // map is the ol.Map instance
  window['ol3d'] = ol3d;
  ol3d.setEnabled(false);
  state.element3D.style.visibility = "hidden";
}


function onCesiumReady({ Cesium, viewer }) {
  window.Cesium = Cesium;
  window.viewer = viewer;
  viewer.clockViewModel.currentTime = Cesium.JulianDate.now(new Date());
  viewer.clockViewModel.shouldAnimate = true; //如果长时间未关闭3d窗口，昼夜会变化
  viewer.clockViewModel.multiplier = 1; //默认速度multiplier等于1
  viewer.scene.globe.enableLighting = true; //晨昏线
  // 禁用cesium默认双击会调用trackedEntity事件
  viewer.trackedEntity = undefined;
  viewer.cesiumWidget.screenSpaceEventHandler.removeInputAction(
    Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK
  );
  useMapStore().setViewer(viewer);
  useMapStore().setCesium(Cesium);
  let layer = new Cesium.WebMapTileServiceImageryProvider({
    url: "http://t0.tianditu.gov.cn/img_w/wmts?tk=b94d96402557b0d5d2e17c5eb93610dc",
    layer: "img",
    style: "default",
    tileMatrixSetID: "w",
    format: "tiles",
    maximumLevel: 18,
    credit: '天地图'
  });
  const terrainLayer = new Cesium.CesiumTerrainProvider({
    url: 'https://data.marsgis.cn/terrain'
  });
  // const terrainLayer = new Cesium.ArcGISTiledElevationTerrainProvider(
  //   {
  //     url: "https://elevation3d.arcgis.com/arcgis/rest/services/WorldElevation3D/Terrain3D/ImageServer",
  //     token: "KED1aF_I4UzXOHy3BnhwyBHU4l5oY6rO6walkmHoYqGp4XyIWUd5YZUC1ZrLAzvV40pR6gBXQayh0eFA8m6vPg.."
  //   });
  viewer.imageryLayers.addImageryProvider(layer);
  // viewer.imageryLayers.addImageryProvider(new Cesium.UrlTemplateImageryProvider({
  //   url: "https://gac-geo.googlecnapps.cn/maps/vt?lyrs=s,m&gl=CN&x={x}&y={y}&z={z}",
  //   credit: "谷歌影像",
  //   maximumLevel: 22,
  // }))

  init2Dand3D();
  const scene = window['ol3d'].getCesiumScene()
  scene.terrainProvider = terrainLayer
}

// 切换到三维视图，添加三维数据
function swicthFun() {
  // state.camera.checkCameraChange();
  state.element2D.style.visibility = switchbtn.value ? "hidden" : "visible";
  state.element3D.style.visibility = switchbtn.value ? "visible" : "hidden";
  state.element2D3D.style.display = switchbtn.value ? "none" : "block";
  mouseShow.value = !switchbtn.value;
  if (useMapStore().$state.workspace != "") {
    workspaceShow.value = false;
  } else {
    workspaceShow.value = true;
  }
}
function isOpenWorkSpace(val) {
  workspaceShow.value = val;
}
/* 转换坐标文本样式 */
function formatCoordinate(fractionDigits) {
  return (
    /**
     * @param {Coordinate} coordinate Coordinate.
     * @return {string} String XY.
     */
    function (coordinate) {
      return '经纬度：' + toStringXY(coordinate, fractionDigits);
    }
  );
}
// 鼠标点击分割线时
function tiggerMouseDown(e) {
  document.addEventListener('mousemove', tiggerMouseMove);
  document.addEventListener('mouseup', tiggerMouseUp);
  triggerLeftOffset.value = e.pageX - e.srcElement.getBoundingClientRect().left;
}
// 鼠标开始拖拽分割线
function tiggerMouseMove(e) {
  const clientRect = proxy.refs.splitPane.getBoundingClientRect();
  let paneLengthPercent = 0;
  const offset = e.pageX - clientRect.left - triggerLeftOffset.value + triggerLength.value / 2;
  paneLengthPercent = (offset / clientRect.width) * 100;
  if (paneLengthPercent < 10) {
    paneLengthPercent = 10
  }
  if (paneLengthPercent > 90) {
    paneLengthPercent = 90
  }
  let element2D = <HTMLImageElement>document.querySelector('.ol-ol');
  element2D.style.width = paneLengthPercent + '%';
}
// 鼠标抬起
function tiggerMouseUp(e) {
  document.removeEventListener('mousemove', tiggerMouseMove)
}

// 鼠标经过选中要素
function selectFeatureByHover() {
  useMapStore().$state.olmap?.on('pointermove', function (e) {
    if (selected !== null) {
      selected.setStyle(undefined);
      selected = null;
    }

    useMapStore().$state.olmap?.forEachFeatureAtPixel(e.pixel, function (f) {
      let selectStyle = new Style({
        fill: new Fill({
          color: 'rgba(0,0,255,0.2)'
        }),
        stroke: new Stroke({
          color: getColor(f.getProperties().Layer),
          width: 2
        }),
        text: new Text({
          text: f.getProperties().Text,
          font: '10px sans-serif',
          textAlign: "left",
          textBaseline: "middle",
          fill: new Fill({
            color: getColor(f.getProperties().Layer)
          }),
          placement: "point",
          overflow: false
        })
      })
      selected = f;
      selectStyle.getStroke().setWidth(3);
      selectStyle.getText().setFont('12px sans-serif');
      f.setStyle(selectStyle);
      return true;
    });
  });
}

// 选中要素弹出弹出框
function changeSelectInteraction() {
  if (select !== null) {
    useMapStore().$state.olmap?.removeInteraction(select);
  }
  select = new Select({
    style: new Style({
      fill: new Fill({
        color: [75, 126, 255, 0.6]
      }),
      stroke: new Stroke({
        width: 2,
        color: '#FFFF00',
        lineDash: [8, 4],
        lineCap: 'butt'
      }),
      image: new Circle({
        fill: new Fill({
          color: 'rgba(255,255,255,0.8)'
        }),
        stroke: new Stroke({
          color: '#EE0000',
          width: 2,
        }),
        radius: 7,
      }),
    }),
  })

  if (select !== null) {
    useMapStore().$state.olmap?.addInteraction(select);
    select.on('select', function (e) {
      if (e.target.getFeatures().getArray().length == 1) {
        selectFeatures.value = e.target.getFeatures().getArray()[0];
        if (e.target.getFeatures().getArray().length != 0) {
          popShow.value = true;
        }
      }
    });
  }
}

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 closePopup() {
  popShow.value = false;
}
</script>

<style scoped lang="scss">
:deep(.el-switch__label) {
  color: #fff;
}

.maps-container {
  position: relative;
  width: 100%;
  height: calc(100vh - 60px);
  overflow: hidden;

  .switch-box {
    position: absolute;
    right: 90px;
    top: 10px;
    z-index: 10;
  }

  .ol-3d {
    width: 100%;
    height: calc(100vh - 60px);
    display: flex;
    flex-direction: direction;

    .ol-ol {
      height: 100%;
      width: 100%;
    }

    .move-line {
      display: none;
      background-color: #151515;
      border-left: 1px solid #fff;
      border-right: 1px solid #fff;
      cursor: col-resize;
    }

    .ol-cesium {
      position: relative;
      height: 100%;
      // flex: 1;
    }
  }


  .custom-mouse-position {
    position: absolute;
    line-height: 35px;
    width: 200px;
    text-align: center;
    background-color: #151515;
    right: 0px;
    bottom: 0px;
    color: #fff;
  }
}

.ol-popup {
  position: absolute;
  background-color: white;
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);
  padding: 15px;
  border-radius: 10px;
  border: 1px solid #cccccc;
  top: 42px;
  right: 0px;
  min-width: 280px;
  z-index: 16;

  .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;
  }
}
</style>
<style>
:deep(#olCesium .cesium-credit-logoContainer) {
  display: none;
}
</style>