<template>
  <div class="layer-list-panel" :class="{ 'fix-layer-list-panel': leftPanelHide }">
    <div class="layer-list-panel-title">
      <div class="title">
        <img src="@/assets/image/common/layerIcon.png" alt="" />
        <span style="margin-left: 0.08rem">资源列表</span>
      </div>
      <div @click="onExpandChange" style="cursor: pointer">
        <img v-show="isExpanded" src="@/assets/image/common/arrow-up.png" style="width: 14px; height: 12px" />
        <img v-show="!isExpanded" src="@/assets/image/common/arrow-up.png" style="transform: rotate(180deg); width: 14px; height: 12px" />
      </div>
    </div>

    <div class="layer-list-panel-content" v-show="isExpanded">
      <el-tree ref="treeRef" :data="treeData" show-checkbox node-key="id" :props="defaultProps" @check="onCheckChange" :default-expanded-keys="['1']">
        <template #default="{ node, data }">
          <span class="custom-tree-node">
            <span>{{ node.label }}</span>
            <i v-if="data.loading" class="el-icon-loading" style="margin-left: 4px; color: #409eff"></i>
            <i v-if="data.error" class="el-icon-warning" style="margin-left: 4px; color: #f56c6c" :title="data.error"></i>
          </span>
        </template>
      </el-tree>
    </div>
  </div>
</template>

<script>
import * as mars3d from 'mars3d'
let layerCache = {}
let graphicsLayer = null
let csqGraphicsLayer = null
export default {
  name: 'LayerListView',
  data() {
    return {
      leftPanelHide: false,
      isExpanded: true,
      defaultProps: { children: 'children', label: 'label' },
      treeData: [
        {
          id: '1',
          label: '综合信息',
          children: [
            {
              id: '1-1',
              label: '生态区',
              children: [
                { id: '1-1-1', label: '提防背河坡脚线', meta: { type: 'polyline', url: '/sddnWeihe/geojson/提防背河坡脚线.geojson' } },
                { id: '1-1-2', label: '河道管理范围线', meta: { type: 'polyline', url: '/sddnWeihe/geojson/河道管理范围线.geojson' } },
                { id: '1-1-3', label: '一级管控区界限', meta: { type: 'polyline', url: '/sddnWeihe/geojson/一二级管控区界限.geojson' } },
                { id: '1-1-4', label: '生态区界限', meta: { type: 'polyline', url: '/sddnWeihe/geojson/生态区界限.geojson' } },
                { id: '1-1-5', label: '城市核心区', meta: { type: 'polyline', url: '/sddnWeihe/geojson/城市核心区.geojson' } },
                { id: '1-1-6', label: '农村区段', meta: { type: 'polyline', url: '/sddnWeihe/geojson/农村区段.geojson' } },
                { id: '1-1-8', label: '城市核心区（右岸）', meta: { type: 'polyline', url: '/sddnWeihe/geojson/城市核心区右岸.geojson' } },
                { id: '1-1-9', label: '农村区段（右岸）', meta: { type: 'polyline', url: '/sddnWeihe/geojson/农村区段右岸.geojson' } }
              ]
            },
            { id: '1-2', label: '监测设备', type: 'monitor' },
            {
              id: '1-3',
              label: '入河排水（污）口',
              children: [
                { id: '1-3-1', label: '兴平城市总排口', meta: { type: 'point', url: '/sddnWeihe/geojson/兴平城市总排口.geojson' } },
                { id: '1-3-2', label: '兴平城市污水处理厂排口', meta: { type: 'point', url: '/sddnWeihe/geojson/兴平城市总排口2.geojson' } },
                { id: '1-3-3', label: '新兴纺织园污水处理厂排口', meta: { type: 'point', url: '/sddnWeihe/geojson/新兴纺织园污水处理厂排口.geojson' } }
              ]
            },
            {
              id: '1-4',
              label: '河道管理站',
              children: [
                { id: '1-4-1', label: '庄头管理站', meta: { type: 'point', url: '/sddnWeihe/geojson/庄头管理站.geojson' } },
                { id: '1-4-2', label: '汤坊管理站', meta: { type: 'point', url: '/sddnWeihe/geojson/汤坊管理站.geojson' } },
                { id: '1-4-3', label: '阜寨管理站', meta: { type: 'point', url: '/sddnWeihe/geojson/阜寨管理站.geojson' } }
              ]
            }
          ]
        },
        {
          id: '2',
          label: '水文监测',
          children: [
            { id: '2-1', label: '水文监测点1', meta: { type: 'point', url: '/sddnWeihe/geojson/sw1.geojson' } },
            { id: '2-2', label: '水文监测点2', meta: { type: 'point', url: '/sddnWeihe/geojson/sw2.geojson' } }
          ]
        },
        {
          id: '3',
          label: '采砂区',
          children: [
            { id: '3-1', label: '兴平市宜空采砂区', type: 'csq', meta: { type: 'polygon', url: '/sddnWeihe/geojson/宜空采砂区.geojson' } },
            { id: '3-2', label: '兴平市团结采砂区', type: 'csq', meta: { type: 'polygon', url: '/sddnWeihe/geojson/团结采砂区.geojson' } },
            { id: '3-3', label: '兴平市汤坊龙兴1区采砂区', type: 'csq', meta: { type: 'polygon', url: '/sddnWeihe/geojson/坊龙兴1区采砂区.geojson' } }
          ]
        },
        {
          id: '4',
          label: '防汛应急预案',
          type: 'plan',
          children: [
            { id: '4-1', type: 'plan', label: '2025年度渭河兴平段水灾害防御工作方案' },
            { id: '4-2', type: 'plan', label: '2025年度渭河水灾害防御工作方案' },
            { id: '4-3', type: 'plan', label: '陕西省防汛应急预案' }
          ]
        }
      ],
      mainMenu: '',
      checkedNodes: []
    }
  },
  created() {
    this.mainMenu = this.$route.params.menu
  },
  mounted() {
    this.$globalEventBus.$on('toggleLeftPanel', (val) => {
      this.leftPanelHide = val
    })
    this.$globalEventBus.$on('closePlanDialog', (data) => {
      this.checkedNodes = []
      const ids = data.map((item) => item.id)
      this.cancelCheckNode(ids)
    })
  },
  watch: {
    mainMenu: {
      handler(val) {
        if (val === 'hydrologicInfo') {
          this.handleData(true)
        } else {
          this.handleData(false)
        }
      }
    }
  },
  methods: {
    //关闭防汛预案弹窗后取消选中
    cancelCheckNode(ids) {
      const currentCheckedKeys = this.$refs.treeRef.getCheckedKeys(true)
      const newArray = currentCheckedKeys.filter((item) => !ids.includes(item))
      this.$refs.treeRef.setCheckedKeys(newArray)
    },
    onExpandChange() {
      this.isExpanded = !this.isExpanded
    },

    async onCheckChange(node, checkData) {
      const { checkedKeys, checkedNodes } = checkData
      const id = node.id
      const isChecked = checkedKeys.includes(id)

      // 维护选中的预案节点
      this.checkedNodes = checkedNodes.filter((item) => item.type === 'plan' && !item.children)

      // ================== 选中 ==================
      if (isChecked) {
        if (node.type === 'plan') {
          this.$globalEventBus.$emit('showPlanDialog', { list: this.checkedNodes })
          return
        }
        if (node.type === 'monitor') {
          if (graphicsLayer) {
            graphicsLayer.show = true
          } else {
            this.getMonitorData()
          }
          return
        }
        if (node.children?.length) {
          // 递归加载所有叶子节点
          await this.loadAllLeafLayers(node.children)
          return
        }

        if (node.meta?.url) {
          if (layerCache[id]) {
            layerCache[id].show = true
          } else {
            await this.loadGeoJsonLayer(node)
            if (node.type === 'csq') {
              this.getCsqLayer(node.label)
            }
          }
        }
      }
      // ================== 取消选中 ==================
      else {
        if (node.type === 'plan') {
          this.$globalEventBus.$emit('showPlanDialog', { list: this.checkedNodes })
          return
        }
        if (node.type === 'monitor') {
          this.removeMonitorData()
          return
        }
        if (node.children?.length) {
          // 递归删除所有叶子节点
          this.removeAllLeafLayers(node.children)
          return
        }
        if (node.type === 'csq') {
          this.removeCsqLayer(node.label)
        }
        this.removeLayer(id)
      }
    },

    // 批量加载叶子节点
    async loadAllLeafLayers(children) {
      for (const child of children) {
        if (child.children?.length) {
          await this.loadAllLeafLayers(child.children)
        } else if (child.meta?.url) {
          if (layerCache[child.id]) {
            layerCache[child.id].show = true
          } else {
            await this.loadGeoJsonLayer(child)
            if (child.type === 'csq') {
              this.getCsqLayer(child.label)
            }
          }
        }
      }
    },

    // 批量删除叶子节点
    removeAllLeafLayers(children) {
      for (const child of children) {
        if (child.children?.length) {
          this.removeAllLeafLayers(child.children)
        } else {
          this.removeLayer(child.id)
          if (child.type === 'csq') {
            this.removeCsqLayer(child.label)
          }
        }
      }
    },

    // 删除图层的通用方法
    removeLayer(id) {
      if (layerCache[id]) {
        try {
          window.map.removeLayer(layerCache[id])
        } catch (e) {
          console.warn(`removeLayer failed: ${id}`, e)
        }
        delete layerCache[id]
      }
    },

    // 加载GeoJson图层的通用方法
    async loadGeoJsonLayer(node) {
      const id = node.id
      if (layerCache[id]) {
        layerCache[id].show = true
        return
      }
      this.$set(node, 'loading', true)
      this.$set(node, 'error', '')
      try {
        const layer = new mars3d.layer.GeoJsonLayer({
          id,
          name: node.label,
          url: node.meta.url,
          clampToGround: true,
          symbol: this.getStyleByName(node.label),
          flyTo: true
        })
        window.map.addLayer(layer)
        this.bindEvent(layer)
        layerCache[id] = layer

        // 父子关联
        const parent = this.$refs.treeRef.getNode(id).parent
        if (parent?.data?.id) {
          layer.options.parentId = parent.data.id
        }
      } catch (e) {
        this.$set(node, 'error', e.message || '加载失败')
      } finally {
        this.$set(node, 'loading', false)
      }
    },
    getStyleByName(name) {
      if (name === '生态区界限') {
        return { type: 'polyline', styleOptions: { color: '#0c5b0f', width: 2 } }
      } else if (name === '提防背河坡脚线') {
        return { type: 'polyline', styleOptions: { color: '#c53632', width: 2 } }
      } else if (name === '河道管理范围线') {
        return { type: 'polyline', styleOptions: { color: '#12641c', width: 2 } }
      } else if (name === '一级管控区界限') {
        return {
          type: 'polyline',
          styleOptions: { width: 2, materialType: mars3d.MaterialType.PolylineDash, materialOptions: { color: '#12641c', dashLength: 60 } }
        }
      } else if (name === '城市核心区' || name === '农村区段') {
        return {
          type: 'polygon',
          styleOptions: {
            color: '#194830',
            opacity: 0.6,
            outline: true,
            outlineWidth: 1,
            outlineColor: '#57e0a9'
          }
        }
      } else if (name === '城市核心区（右岸）' || name === '农村区段（右岸）') {
        return {
          type: 'polygon',
          styleOptions: {
            color: '#368d63',
            opacity: 0.3,
            outline: true,
            outlineWidth: 1,
            outlineColor: '#57e0a9'
          }
        }
      } else if (name.indexOf('水文') > -1) {
        const ptStyle = this.getPointStyle(name)
        return {
          type: 'billboard',
          styleOptions: {
            image: require('./image/水文站.png'),
            ...ptStyle
          }
        }
      } else if (name.indexOf('排口') > -1) {
        const ptStyle = this.getPointStyle(name)
        return {
          type: 'billboard',
          styleOptions: {
            image: require('./image/排污口.png'),
            ...ptStyle
          }
        }
      } else if (name.indexOf('管理站') > -1) {
        const ptStyle = this.getPointStyle(name)
        return {
          type: 'billboard',
          styleOptions: {
            image: require('./image/管理站.png'),
            ...ptStyle
          }
        }
      } else if (name.indexOf('采砂区') > -1) {
        return {
          type: 'polygon',
          styleOptions: {
            label: { text: name, font_size: 14, outline: true, outlineColor: '#000000', outlineWidth: 2 },
            clampToGround: true,
            materialType: this.mars3d.MaterialType.Grid,
            materialOptions: { color: '#cc9648', cellAlpha: 0.5 },
            outline: true,
            outlineWidth: 1,
            outlineColor: '#cc9648'
          }
        }
      }
    },

    getPointStyle(name) {
      return {
        scale: 0.8,
        label: { text: name, font_size: 14, outline: true, outlineColor: '#000000', outlineWidth: 2, pixelOffsetY: -60 },
        clampToGround: true,
        horizontalOrigin: this.Cesium.HorizontalOrigin.CENTER,
        verticalOrigin: this.Cesium.VerticalOrigin.BOTTOM,
        pixelOffset: new this.Cesium.Cartesian2(0, -6), // 偏移量
        distanceDisplayCondition: new this.Cesium.DistanceDisplayCondition(0.0, 500000) // 按视距显示
      }
    },
    // 处理水文站数据
    handleData(isShow) {
      const nodeIds = ['2-1', '2-2']
      this.$nextTick(() => {
        nodeIds.forEach((id) => {
          const node = this.$refs.treeRef.getNode(id)
          if (!node) return
          // 直接修改 checked 状态
          this.$refs.treeRef.setChecked(node, isShow)
          // 手动触发 check 事件
          this.$refs.treeRef.$emit(
            'check',
            node.data, // 选中的节点数据
            {
              checkedKeys: this.$refs.treeRef.getCheckedKeys(),
              checkedNodes: this.$refs.treeRef.getCheckedNodes()
            }
          )
        })
      })
    },

    // 绑定点击事件
    bindEvent(layer) {
      const _that = this
      if (layer.id === '2-1' || layer.id === '2-2') {
        layer.on(mars3d.EventType.click, function (event) {
          _that.$globalEventBus.$emit('clickWaterStation', event)
        })
      }
    },
    getMonitorData() {
      graphicsLayer = new this.mars3d.layer.GraphicLayer()
      window.map.addLayer(graphicsLayer)
      window.requestSDK('/sddnWeiHe/device/deviceSimpleList', { pageNum: 1, pageSize: 10, platFlag: '1', operType: '0' }, {}, 'post').then((res) => {
        const data = res.data
        data.forEach((point) => {
          const graphic = new mars3d.graphic.BillboardEntity({
            position: [point.longitude, point.latitude],
            style: {
              image: require('./image/camera.png'),
              scale: 0.8,
              clampToGround: true,
              horizontalOrigin: this.Cesium.HorizontalOrigin.CENTER,
              verticalOrigin: this.Cesium.VerticalOrigin.BOTTOM,
              pixelOffset: new this.Cesium.Cartesian2(0, -6), // 偏移量
              distanceDisplayCondition: new this.Cesium.DistanceDisplayCondition(0.0, 500000) // 按视距显示
            },
            attr: { ...point }
          })
          graphicsLayer.addGraphic(graphic)
          let that = this
          graphic.on(this.mars3d.EventType.click, function () {
            const pointData = graphic.attr
            that.fetchUrl(pointData).then((res) => {
              if (res.code == 4001) {
                that.$message.warning(JSON.parse(res.msg).resultMsg)
              } else if (res.code == 400) {
                that.$message.error(res.msg)
              } else {
                const url = res.data.streamUrl
                that.$set(pointData, 'url', url)
                that.$globalEventBus.$emit('clickVideoPlay', { point: pointData, visible: true, type: 'click' })
              }
            })
          })
        })
        graphicsLayer.flyTo()
      })
    },
    fetchUrl(item) {
      return new Promise((resolve, reject) => {
        window
          .requestSDK(
            '/ttvideo/video/player/getVideoRealtimeUrl',
            {
              deviceCode: item.deviceCode,
              channelCode: item.channelCode,
              netType: '1',
              protocolType: 5,
              streamType: 1
            },
            {},
            'post'
          )
          .then(async (res) => {
            resolve(res)
          })
      })
    },
    removeMonitorData() {
      if (graphicsLayer) {
        graphicsLayer.show = false
        // window.map.removeLayer(graphicsLayer)
      }
    },
    // 采砂区柱状图
    getCsqLayer(name) {
      const coorList = {
        兴平市宜空采砂区: [108.352091, 34.202407, 100],
        兴平市团结采砂区: [108.360076, 34.20512, 100],
        兴平市汤坊龙兴1区采砂区: [108.474301, 34.21255, 100]
      }
      const lengthList = {
        兴平市宜空采砂区: 300,
        兴平市团结采砂区: 500,
        兴平市汤坊龙兴1区采砂区: 600
      }
      if (csqGraphicsLayer) {
        csqGraphicsLayer.show = true
      } else {
        csqGraphicsLayer = new this.mars3d.layer.GraphicLayer()
        window.map.addLayer(csqGraphicsLayer)
      }
      const position = coorList[name]
      const graphic = new this.mars3d.graphic.CylinderEntity({
        id: name,
        position,
        style: {
          length: lengthList[name],
          topRadius: 20.0,
          bottomRadius: 20.0,
          color: '#85bc68',
          opacity: 0.45,
          clampToGround: true
        }
      })
      csqGraphicsLayer.addGraphic(graphic)
    },
    removeCsqLayer(name) {
      if (csqGraphicsLayer) {
        const graphic = csqGraphicsLayer.getGraphicById(name)
        csqGraphicsLayer.removeGraphic(graphic)
      }
    }
  },
  destroyed() {
    this.$globalEventBus.$off('closePlanDialog')
    this.$globalEventBus.$off('toggleLeftPanel')
    // 把图层上绑定的事件也清掉
    Object.values(layerCache).forEach((l) => l.off('click'))
    window.map.removeLayer(graphicsLayer)
    graphicsLayer = null
    window.map.removeLayer(csqGraphicsLayer)
    csqGraphicsLayer = null
  }
}
</script>

<style lang="scss" scoped>
.layer-list-panel {
  position: absolute;
  top: px-to-rem(80);
  left: px-to-rem(480);
  width: px-to-rem(240);
  padding: px-to-rem(10);
  background: #1b2535;
  border-radius: 6px;
  opacity: 0.85;
  z-index: 1000;
  transition: left 0.3s ease-in-out;
  .layer-list-panel-title {
    margin-bottom: px-to-rem(10);
    height: px-to-rem(30);
    line-height: px-to-rem(30);
    display: flex;
    justify-content: space-between;
    align-items: center;
    .title {
      display: flex;
      justify-content: center;
      align-items: center;
      font-size: px-to-rem(18);
      color: #eaf3fe;
    }
  }
  .layer-list-panel-content {
    margin: px-to-rem(-10);
    padding: px-to-rem(10);
    max-height: px-to-rem(340);
    overflow: auto;
    :deep(.el-tree) {
      background: transparent;
      color: #fff;
      .el-tree-node__content {
        height: unset;
      }
      .el-tree-node__content:hover,
      .el-upload-list__item:hover,
      .el-tree-node:focus > .el-tree-node__content {
        background-color: transparent;
        height: unset;
      }
      .el-tree-node__label {
        white-space: wrap;
      }
    }
    .custom-tree-node {
      font-size: px-to-rem(16);
      overflow: hidden;
      white-space: nowrap;
      text-overflow: ellipsis;
    }
  }
}
.fix-layer-list-panel {
  left: px-to-rem(20);
}
</style>
