<template>
  <div class="map-container" v-loading='maploading'>
    <div class="mainmap"></div>
    <transition name="el-zoom-in-top">
      <div v-show="showMapLengend" class="map-legend">
        <div class="map-legend-title">
          <span>图例</span>
          <span ref="legendCloser" style="float: right; cursor: pointer" title="收缩" @click="legendChange">▼</span>
        </div>
        <div
          v-show="showLegendBox"
          class="map-legend-item"
          v-for="(item, index) in legendData"
          :key="index"
        >
          <div style="flex: 0.3; text-align: center">
            <div :class="'map-legend-' + item.type" :style="'background-color:' + item.color"></div>
          </div>
          <div style="flex: 0.7; text-align: center">
            <div class="map-legend-label">{{ item.label }}</div>
          </div>
        </div>
      </div>
    </transition>
  </div>
</template>

<script>
import CesiumUtil from '@/views/pipelineDefect/common/cesiumUtil'
import HandleManage from '@/views/pipelineDefect/common/cesiumEvent'
import GraphicUtil from '@/views/pipelineDefect/common/graphic'
import CesiumDraw from '@/views/pipelineDefect/common/cesiumDraw'

import popupWindow from '@/views/pipelineDefect/components/popupWindow.vue'
import { LegendConfig } from '@/views/pipelineDefect/common/legendConfig'
import { appconfig } from 'staticPub/config'
import { projUtil } from '@/views/pipelineDefect/common/proj'

import defectImg1 from '@/assets/images/traingle1.png'
import defectImg2 from '@/assets/images/traingle2.png'
import defectImg3 from '@/assets/images/traingle3.png'
import defectImg4 from '@/assets/images/traingle4.png'
import defectImg0 from '@/assets/images/traingle0.png'

import { Feature } from 'ol'
import { LineString, Point, Polygon } from 'ol/geom'
import * as turf from '@turf/turf'

export default {
    components: { popupWindow },
    data () {
        return {
            popupPosition: null,
            showPopup: false,
            baselayer: [],
            mapService: ['img', 'theme'],
            cesiumUitl: null,
            center: [104.1629, 30.0039, 3e3], // 仁寿坐标
            projUtil: null,

            currentDataProjName: appconfig.currPRJ,

            lightLayerName: 'bslightlayer', // 高亮的图层名
            propertyName: 'bsdata', // 添加到地图实体里的数据名
            geometryType: 'geometryType', // 类型区分
            lightStyle: {
                line: 'rgba(0, 255, 255, 0.6)',
                point: 'rgba(0, 255, 255, 0.6)'
            },
            lightGraphic: null,
            
            showLegendBox: true,
            showMapLengend: false,
            legendData: [],
            maploading: false,
            //
            removeListener: null
        }
    },
    methods: {
        changeLoading (status) {
            this.maploading = status
        },
        // 初始化地图
        initMap () {
            var viewer = CesiumUtil.getInitViewer(this.$el.getElementsByClassName('mainmap')[0])
            this.cesiumUitl = new CesiumUtil(viewer)
            this.graphicUtil = new GraphicUtil()
            this.projUtil = new projUtil()
            this.projUtil.resgis(this.currentDataProjName)
            this.viewer = viewer
            
            this.viewer.scene.screenSpaceCameraController.enableTilt = false // 不允许倾斜视角

            this.initCesiumWidget ()
            this.initCesiumStatus() // 初始化 cesium 状态
            this.initBaseMap() // 加载图层，包括专题图，影像图
            this.initTianditu() // 加载矢量图，poi

            this.initEvent()

            // 
            let { lon, lat, height } = this.AppX.appConfig.initPosition
            console.log('定位')
            this.cesiumUitl.setView(CesiumUtil.degrees2Car3(parseFloat(lon), parseFloat(lat), parseFloat(height)))


            let dataSources = this.viewer.dataSources
            this.pDataSource = new Cesium.CustomDataSource('line')
            dataSources.add(this.pDataSource)
            this.dDataSource = new Cesium.CustomDataSource('defect')
            dataSources.add(this.dDataSource)

            this.$emit('afterLoad')
        },
        //
        initEvent () {
          let timer = null
          this.removeListener = this.viewer.camera.changed.addEventListener(evt => {
            timer && clearTimeout(timer)
            timer = null
            if (!timer) {
              timer = setTimeout(() => {
                let [xmin, ymin, xmax, ymax] = this.getCurrExtent()
                let coors = [ [ [xmin, ymax], [xmax, ymax], [xmax, ymin], [xmin, ymin], [xmin, ymax] ] ]
                this.$emit('mapMoveEvent', new Feature({ geometry: new Polygon(coors) }))
              }, 100)
            }
          })
        },
        // 获取当前地图视野范围（经纬度）
        getCurrExtent () {
          if (!this.$el) { return }
          let that = this
          let extent = []
          let dom = this.$el.getElementsByClassName('mainmap')[0]

          let top = 0, left = 0, right = dom.clientWidth + left, bottom = dom.clientHeight + top
          let topLeftPoint = getCoordinateFromPixel([left, top])
          let bottomRightPoint = getCoordinateFromPixel([right, bottom])
          let xmin = topLeftPoint.lon,
              ymax = topLeftPoint.lat,
              xmax = bottomRightPoint.lon,
              ymin = bottomRightPoint.lat
          return [xmin, ymin, xmax, ymax]

          function getCoordinateFromPixel ([x, y]) {
            let car3 = that.cesiumUitl.xy2Car3({ x, y })
            let degrees = CesiumUtil.car32Degrees(car3)
            return degrees
          }
        },
        // 
        initCesiumWidget () {
            this.viewer._cesiumWidget._creditContainer.style.display = 'none' // 去掉logo
        },
        /**
         * 该方法用于初始化cesium属性
         */
        initCesiumStatus() {
            //开启地形深度测试
            this.viewer.scene.globe.depthTestAgainstTerrain = false
            //关闭灯光
            this.viewer.scene.globe.enableLighting = false
            //globeAlpha导致月球始终可见
            this.viewer.scene.moon.show = false
            //地球表面双面显示
            this.viewer.scene.globe.backFaceCulling = false
            //开启地下模式
            this.viewer.scene.undergroundMode = true
            this.viewer.scene.screenSpaceCameraController.minimumZoomDistance = -1000
            this.viewer.terrainProvider.isCreateSkirt = false //关闭地形裙边
            //设置地球表面颜色
            this.viewer.scene.globe.baseColor = new Cesium.Color(0, 0, 0, 1)
            //帧率工具
            this.viewer.scene.debugShowFramesPerSecond = false
            const nowDate = new Date(Date.now())
            nowDate.setHours(16) //设置系统时间为12点,时差12小时
            nowDate.setMinutes(0)
            this.viewer.clock.currentTime = Cesium.JulianDate.fromDate(nowDate)
            this.viewer.cesiumWidget.screenSpaceEventHandler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK)
        },
        /**
         * 初始化基础底图
        */
        initBaseMap() {
            this.baseMapConfig()
            let layerInfo = this.baselayer
            layerInfo.forEach(item => {
                if (item.show) {
                    const gisItem = this.AppX.appConfig.gisResource[item.type].config[item.name]
                    const url = gisItem.url
                    if (this.mapService.includes(item.type)) {
                        this.viewer.imageryLayers.addImageryProvider(new Cesium.SuperMapImageryProvider({ url: url, credit: item.name }))
                    } else if ((item.type = 'mvt')) {
                        this.viewer.scene.addVectorTilesMap({ url: url, name: item.name })
                    }
                }
            })
        },
        /**
         * 地图服务配置
         */
        baseMapConfig() {
            const source = this.AppX.appConfig.gisResource
            const mapList = this.mapService
            const baseLayer = []
            for (let name in source) {
                if (mapList.includes(name)) {
                    const config = source[name].config
                    for (let key in config) {
                        const item = config[key]
                        baseLayer.push({
                            name: key,
                            type: name,
                            show: item.isDisplay === '0' ? false : true
                        })
                    }
                }
            }
            this.baselayer = baseLayer
        },
        /**
         * 天地图加载
         */
        initTianditu () {
            const layerType = 'vec_w'
            const poiType = 'cva_w'
            const layerName = layerType.split('_')[0]
            const poiName = poiType.split('_')[0]
            const token = this.$store.state.cesiumMap.tdttoken
            const url =
                'https://t{s}.tianditu.gov.cn/' +
                layerType +
                '/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=' +
                layerName +
                '&TILEMATRIXSET=w&TILEMATRIX={TileMatrix}&TILEROW={TileRow}&TILECOL={TileCol}&STYLE=default&FORMAT=tiles&tk=' +
                token
            const poiurl =
                'https://t{s}.tianditu.gov.cn/' +
                poiType +
                '/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=' +
                poiName +
                '&TILEMATRIXSET=w&TILEMATRIX={TileMatrix}&TILEROW={TileRow}&TILECOL={TileCol}&STYLE=default&FORMAT=tiles&tk=' +
                token
            const imagelayers = this.viewer.imageryLayers
            const layerlen = imagelayers.length
            const subdomains = ['0', '1', '2', '3', '4', '5', '6', '7']
            //中台
            const imglayer = new Cesium.WebMapTileServiceImageryProvider({
                //影像底图
                url: new Cesium.Resource({
                    url: url,
                    headers: {
                        Accept: 'image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8'
                    }
                }),
                subdomains,
                credit: 'tianditu_base',
                layer: 'tdtVecLayer',
                style: 'default',
                maximumLevel: 17,
                format: 'image/jpeg',
                tileMatrixSetID: 'GoogleMapsCompatible', //使用谷歌的瓦片切片方式
                show: true
            })

            const poilayer = new Cesium.WebMapTileServiceImageryProvider({
                //影像底图
                url: new Cesium.Resource({
                    url: poiurl,
                    headers: {
                        Accept: 'image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8'
                    }
                }),
                subdomains: subdomains,
                credit: 'tianditu_poi',
                layer: 'tdtCvaLayer',
                style: 'default',
                format: 'image/jpeg',
                maximumLevel: 17,
                tileMatrixSetID: 'GoogleMapsCompatible', //使用谷歌的瓦片切片方式
                show: true
            })
            imagelayers.addImageryProvider(imglayer, 1)
            imagelayers.addImageryProvider(poilayer, 2)
        },
        // -------------------------- 方法 -------------------------
        getFeatures(data) {
            const colors = [
                { level: 'Ⅰ', color: 'green' },
                { level: 'Ⅱ', color: 'blue' },
                { level: 'Ⅲ', color: 'pink' },
                { level: 'Ⅳ', color: 'red' }
            ], defaultColor = '#070358'
            let features = { pipeDefectFeatures: [], funcDefectFeatures: [], strucDefectFeatures: [], normal: [] }
            data.forEach(defect => {
                let { endPointXLocation, endPointYLocation, startPointXLocation, startPointYLocation } = defect
                if (startPointXLocation && startPointYLocation && endPointXLocation && endPointYLocation) {
                    let startPoint = this.projUtil.transform([Number(startPointXLocation), Number(startPointYLocation)], this.currentDataProjName, 'proj84')
                    let endPoint = this.projUtil.transform([Number(endPointXLocation), Number(endPointYLocation)], this.currentDataProjName, 'proj84')

                    let lineCar3 = CesiumUtil.degreesArray2Car3([startPoint, endPoint].flat())
                    //
                    let findFuncColor = colors.find(colorObj => defect['funcClass'] && defect['funcClass'].includes(colorObj.level))
                    let findStrucColor = colors.find(colorObj => defect['structClass'] && defect['structClass'].includes(colorObj.level))
                    // 结构性
                    let scolor = findStrucColor ? findStrucColor.color : defaultColor
                    let sFea = this.getEntity('line', lineCar3, { color: scolor }, { ...defect, lineCar3 })
                    features.strucDefectFeatures.push(sFea)
                    // 功能性
                    let fcolor = findFuncColor ? findFuncColor.color : defaultColor
                    let fFea = this.getEntity('line', lineCar3, { color: fcolor }, { ...defect, lineCar3 })
                    features.funcDefectFeatures.push(fFea)
                    // 缺陷
                    if (defect.geometry) {
                        let { x, y } = JSON.parse(defect.geometry)
                        let [lon, lat] = this.projUtil.transform([x, y], this.currentDataProjName, 'proj84')
                        let pointCar3 = CesiumUtil.degrees2Car3(lon, lat, 0)
                        let imgs = [
                            { level: ['一级', '1'], img: defectImg1, index: 0 },
                            { level: ['二级', '2'], img: defectImg2, index: 1 },
                            { level: ['三级', '3'], img: defectImg3, index: 2 },
                            { level: ['四级', '4'], img: defectImg4, index: 3 }
                        ]
                        let findimg = null
                        if (defect.defectLevel) {
                            findimg = imgs.find((colorObj) => colorObj.level.includes(defect['defectLevel']))
                        }
                        if (findimg) {
                            let dFea = this.getEntity('img', pointCar3, { img: findimg.img }, { ...defect, pointCar3 })
                            features.pipeDefectFeatures.push(dFea)
                        }
                    }
                }
            })
            return features
        },
        // 移除所有要素
        removeCesiumGraphics () {
          if (this.pDataSource) {
            let entities = this.pDataSource.entities
            let arr = entities.values
            arr.forEach(e => entities.remove(e))
          }
          if (this.dDataSource) {
            let entities = this.dDataSource.entities
            let arr = entities.values
            arr.forEach(e => entities.remove(e))
          }
        },
        //  加载管线
        addLines (lines) {
            if (!Array.isArray(lines)) {
                lines = [lines]
            }
            lines.forEach(line => {
                this.pDataSource.entities.add(line)
            })
        },
        // 加载缺陷
        addDefects (defects) {
            if (!Array.isArray(defects)) {
                defects = [defects]
            }
            defects.forEach(defect => {
                this.dDataSource.entities.add(defect)
            })
        },
        // 获取图元
        getPrimity (type, positions, style) {
            return this.graphicUtil.getPrimity(type, positions, style)
        },
        // 获取实体
        getEntity (type, positions, style) {
            return this.graphicUtil.getEntity(type, positions, style)
        },
        // --------------------------- 业务 ---------------------------
        // 图例显隐
        showLegend(legendName, visible) {
            if (!legendName) return
            this.legendData = LegendConfig[legendName]
            this.showMapLengend = visible
        },
        legendChange() {
            this.showLegendBox = !this.showLegendBox
            let dom =  this.$refs.legendCloser
            dom.innerHTML = this.showLegendBox ? '▼' : '▲'
        },
        //
        getDefectDataInMap(data, extent, type = '') {
          let that = this
          // 无范围 默认全图
          if (!extent) {
            let [xmin, ymin, xmax, ymax] = this.getCurrExtent()
            let coors = [
              [
                [xmin, ymax],
                [xmax, ymax],
                [xmax, ymin],
                [xmin, ymin],
                [xmin, ymax]
              ]
            ]
            extent = new Feature({ geometry: new Polygon(coors) })
          }
          let filterExtent = turf.polygon(extent.getGeometry().getCoordinates())
          let dFeas = data.map((pipeData) => pipeData.pipeDefects).flat()
          let pFeas = data
          // 范围过滤
          let defectData = filter(dFeas, filterExtent, 1)
          let pipeData = filter(pFeas, filterExtent, 2)

          // 加入地图
          // let feas = this.getFeatures(data)
          // if (type === 1) {
          //   this.addDefects(feas.pipeDefectFeatures)
          // } else if (type ===  2) {
          //   this.addLines(feas.pipeDefectFeatures)
          // } else {
          //   this.addDefects(feas.pipeDefectFeatures)
          //   this.addLines(feas.pipeDefectFeatures)
          // }

          return { pipeData, defectData }

          function filter(features, extent, type) {
            let feas = []
            feas = features.map((feaObj) => {
              let fea = {}
              if (type === 1) {
                let coors = JSON.parse(feaObj.geometry)
                if (!coors) {
                  return null
                }
                fea.geometry = turf.point(that.projUtil.transform([coors.x, coors.y], that.currentDataProjName, 'proj84'))
                for (let key in feaObj) {
                  if (key !== 'geometry') {
                    fea[key] = feaObj[key]
                  }
                }
              } else {
                let { startPointXLocation, startPointYLocation, endPointXLocation, endPointYLocation } = feaObj
                if (!(startPointXLocation && startPointYLocation && endPointXLocation && endPointYLocation)) {
                  return null
                }
                let startPoint = [Number(startPointXLocation), Number(startPointYLocation)]
                let endPoint = [Number(endPointXLocation), Number(endPointYLocation)]
                startPoint = that.projUtil.transform(startPoint, that.currentDataProjName, 'proj84')
                endPoint = that.projUtil.transform(endPoint, that.currentDataProjName, 'proj84')
                fea.geometry = turf.lineString([startPoint, endPoint])
                for (let key in feaObj) {
                  if (key !== 'geometry') {
                    fea[key] = feaObj[key]
                  }
                }
              }
              return fea
            })
            return feas.filter(fea => fea && turf.booleanContains(extent, fea.geometry))
          }
        },
        getDataInMap(data, extent) {
          let that = this
          // 无范围 默认全图
          if (!extent) {
            let [xmin, ymin, xmax, ymax] = new mapUtil(this.map).getCurrentViewExtent()
            let coors = [
              [
                [xmin, ymax],
                [xmax, ymax],
                [xmax, ymin],
                [xmin, ymin],
                [xmin, ymax]
              ]
            ]
            extent = new Feature({ geometry: new Polygon(coors) })
          }
          let filterExtent = turf.polygon(extent.getGeometry().getCoordinates())

          let resData = new Map()
          data = filter(data, 2)
          // 地图加入整改图层
          let colors = this.colors
          let features = []
          data.forEach((pipeData) => {
            let geometry = new LineString(pipeData.geometry.geometry.coordinates)
            if (geometry && pipeData.pipeDefects.length !== 0) {
              let defects = pipeData.pipeDefects.filter(defect => defect.checkSuggest)
              let colorObjs = colors.filter(item => defects.some(defect => item.label.includes(defect.checkSuggest)))
              if (colorObjs.length !== 0) {
                let colorObj = colorObjs[0]
                let feature = new Feature({ geometry })
                feature.setStyle(comSymbol.getLineStyle(5, colorObj.color))
                features.push(feature)
              }
            } else {
              !geometry && console.log('无位置信息')
              pipeData.pipeDefects.length === 0 && console.log('无缺陷数据')
            }
          })
          // 数据整理
          data.forEach(pipeData => {
            let len = pipeData.pipeLength
            let defectData = pipeData.pipeDefects
            defectData.forEach(defect => {
              if (defect.checkSuggest) {
                if (!resData.has(defect.checkSuggest)) {
                  resData.set(defect.checkSuggest, { num: 1, len })
                } else {
                  let data = resData.get(defect.checkSuggest)
                  data.num += 1
                  data.len += len
                }
              }
            })
          })
          let obj = {}
          resData.forEach((value, key) => {
            obj[key] = value
          })
          return obj

          function filter(features, type) {
            let feas = []
            feas = features.map((feaObj) => {
              let fea = {}
              if (type === 1) {
                let coors = JSON.parse(feaObj.geometry)
                if (!coors) {
                  return null
                }
                fea.geometry = turf.point(that.projUtil.transform([coors.x, coors.y], that.currentDataProjName, 'proj84'))
                for (let key in feaObj) {
                  if (key !== 'geometry') {
                    fea[key] = feaObj[key]
                  }
                }
              } else {
                let { startPointXLocation, startPointYLocation, endPointXLocation, endPointYLocation } = feaObj
                if (!(startPointXLocation && startPointYLocation && endPointXLocation && endPointYLocation)) {
                  return null
                }
                let startPoint = [Number(startPointXLocation), Number(startPointYLocation)]
                let endPoint = [Number(endPointXLocation), Number(endPointYLocation)]
                startPoint = that.projUtil.transform(startPoint, that.currentDataProjName, 'proj84')
                endPoint = that.projUtil.transform(endPoint, that.currentDataProjName, 'proj84')
                fea.geometry = turf.lineString([startPoint, endPoint])
                for (let key in feaObj) {
                  if (key !== 'geometry') {
                    fea[key] = feaObj[key]
                  }
                }
              }
              return fea
            })
            return feas.filter((fea) => fea && turf.booleanContains(filterExtent, fea.geometry))
          }
        },
        draw ({ callback }) {
          let drawer = new CesiumDraw(this.viewer)
          drawer.start(callback)
          return drawer
        }
    },
    computed: {
        AppX: function () {
            return this.$store.getters.AppX
        }
    },
    mounted () {
        this.initMap()
    }

}
</script>

<style lang='scss'>
.map-container {
  width: 100%;
  height: 100%;
  position: relative;
  overflow: hidden;
  .mainmap {
    width: 100%;
    height: 100%;
    canvas {
      width: 100% !important;
      height: 100% !important;
      touch-action: none;
    }
    .cesium-viewer-bottom,
    .cesium-viewer-selectionIndicatorContainer,
    .cesium-viewer-infoBoxContainer,
    .cesium-viewer-toolbar,
    .cesium-viewer-zoomIndicatorContainer {
      display: none !important;
    }
    .cesium-viewer-navigationContainer {
      //   left: 0 !important;
      display: none !important;
    }
  }
.map-legend {
  z-index: 99;
  background: #fffc;
  position: absolute;
  bottom: 40px;
  left: 30px;
  min-height: 30px;
  width: 200px;
  border: 1px solid rgb(13, 186, 255);
}

.map-legend-title {
  color: #fff;
  font-weight: 600;
  padding: 3px 10px;
  height: 30px;
  font-size: 15px;
  line-height: 25px;
  background-color: rgb(13, 186, 255);
}
.map-legend-item {
  display: flex;
  height: 20px;
  line-height: 20px;
  font-size: 13px;
  margin: 15px 10px;
}
.map-legend-label {
  margin-left: 5px;
}
.map-legend-rect {
  display: inline-block;
  width: 30px;
  height: 100%;
}
.map-legend-circle {
  display: inline-block;
  width: 10px;
  height: 10px;
  border-radius: 50%;
}
.map-legend-line {
  display: inline-block;
  width: 50px;
  height: 8px;
}
.map-legend-traingle1 {
  transform: scale(0.4);
  background-size: 100% 100%;
  background-image: url('../img/traingle1.png');
  background-repeat: no-repeat;
  width: 36px;
  height: 36px;
}
.map-legend-traingle2 {
  transform: scale(0.4);
  background-size: 100% 100%;
  background-image: url('../img/traingle2.png');
  background-repeat: no-repeat;
  width: 36px;
  height: 36px;
}
.map-legend-traingle3 {
  transform: scale(0.4);
  background-size: 100% 100%;
  background-image: url('../img/traingle3.png');
  background-repeat: no-repeat;
  width: 36px;
  height: 36px;
}
.map-legend-traingle4 {
  transform: scale(0.4);
  background-size: 100% 100%;
  background-image: url('../img/traingle4.png');
  background-repeat: no-repeat;
  width: 36px;
  height: 36px;
}
.map-legend-traingle0 {
  transform: scale(0.4);
  background-size: 100% 100%;
  background-image: url('../img/traingle0.png');
  background-repeat: no-repeat;
  width: 36px;
  height: 36px;
}

}
</style>