<template>
  <div class="widget-pbsTreeManagement">
    <!-- <el-tabs v-model="activeName"> -->
    <!-- <el-tab-pane label="设计" name="design"> -->
    <div class="designSearch" v-if="false">
      <div class="designItem">
        <el-select size="mini" v-model="searchType" @change="searchTypeChange">
          <el-option label="工程名称" value="2"></el-option>
          <el-option label="PBS编码" value="0"></el-option>
          <el-option label="部件标识码" value="1"></el-option>
        </el-select>
      </div>
      <div class="designItem">
        <el-input size="mini" v-model="searchInput" clearable @clear="clearInput">
          <!-- <el-button slot="append" icon="el-icon-search"></el-button> -->
          <el-button slot="append" icon="el-icon-search" @click="searchOperation"></el-button>
        </el-input>
      </div>
      <!-- <div class="designItem">
        <el-button size="mini" type="primary" icon="el-icon-search" @click="searchOperation"></el-button>
      </div> -->
    </div>
    <div class="designTree">
      <el-tree
        :data="treeData"
        :props="props"
        :load="loadNode"
        lazy
        node-key="id"
        highlight-current
        :default-expanded-keys="[1367]"
        :render-content="renderContent"
        @node-click="handleNodeClick"
        @node-contextmenu="exportQRCode"
      ></el-tree>
      <div class="tip" :style="{ left: optionCardX + 'px', top: optionCardY + 'px' }" v-show="tipShow">
        <el-button type="primary" size="mini" @click="exportCurrent">导出二维码</el-button>
      </div>
    </div>
    <!-- </el-tab-pane> -->
    <!-- <el-tab-pane label="竣工" name="completed">暂无</el-tab-pane>
    </el-tabs> -->
  </div>
</template>

<script>
let pbsCustomDataSource = null
let rangeHandler = null
import Vue from 'vue'
import { pbsTreeList_api, pbsTreeSearch_api, pbsTreeMinimum_api, createPdfByType_api } from '@/api/APIs.ts'
import { getListWithRange, getPbsListWithRange } from '@/views/groupPage/apis'
import ProjectInfo from '@/views/groupPage/districtPageModules/customTools/infoComponents/projectInfo.vue'
import PipeUnitInfo from '@/views/groupPage/districtPageModules/pipeUnitInfo/index.vue'
export default {
  name: 'widget-pbsTreeManagement',
  data() {
    return {
      activeName: 'design',
      searchType: '2', //默认为工程名称
      searchInput: '',
      choke: false, //节流
      //设计模块的数据
      originalData: '', //设计模块请求来的原始数据，用于项目名称搜索功能
      fatherNodesData: [], //第一次请求来处理后的父节点数据
      treeData: [],
      tipShow: false,
      optionCardX: '',
      optionCardY: '',
      treeNodeId: '',
      //设计模块的elm绑定属性
      props: {
        label: 'name',
        children: 'children',
        isLeaf: 'leaf'
      },
      pipeInfo: null,
      //外部调用参数
      prjInfoArr: []
    }
  },
  computed: {
    prjId() {
      return this.$store.state.bigScreen.currentPrjId
    }
  },
  methods: {
    //懒加载树状下层
    async loadNode(node, resolve) {
      if (node.level == 0) {
        return this.loadtreeData(resolve)
      }
      if (node.level >= 1 && node.data) {
        if (node.data.levelname == '部件类型') {
          let id = node.data.id
          let res = await this.minimumNodesResult(id)
          if (res) {
            return resolve(res)
          }
        } else {
          return resolve(node.data.children)
        }
      }
    },
    // 获取树状结构列表
    async loadtreeData(resolve) {
      let res = await getListWithRange({ prjId: this.prjId })
      let { result, code } = res
      if (result.length == 0 || code != 1) return
      this.fatherNodesData = this.getPbsTree(result)
      resolve(this.fatherNodesData)
      this.originalData = result
    },
    //结构树最小单元
    async minimumNodesResult(id) {
      let minimumTree = await this.getTreeMinimum(id)
      return minimumTree
    },
    //获取树状结构列表的最小单元
    async getTreeMinimum(val) {
      let res = await pbsTreeMinimum_api({ prjId: this.prjId, id: val })
      let { result } = res
      result.forEach((item) => {
        item.value = item.code
        // item.name = `${item.code}(${item.pipeId})`
        // item.name = `${item.elementCodeName}_${item.code}`
        item.name = `${item.pipeId}_${item.code}`
        item.leaf = true
      })
      return result
    },
    //对后台返回的列表结构处理分类成PBS分支树所需的树状数据
    getPbsTree(results) {
      let that = this
      let dep = 0
      let curPid = []
      function arr2tree(data, parent) {
        let tree = [] // 定义最终输出
        let temp = [] // 定义中间存储用变量
        const usedParent = that.$_.find(curPid, function (item) {
          return item.pid === parent
        })
        if (!usedParent) {
          dep += 1
          curPid.push({ pid: parent, dep: dep })
        }
        for (let i = 0; i < data.length; i++) {
          if (data[i].pid == parent) {
            // 找到父级
            let obj = data[i] // 保存父级
            obj.originname = obj.name
            obj.name = `${obj.name}_${obj.code}`
            obj.leaf = false //用于elementUI的渲染
            obj.prjId = obj.prjid
            obj.prjName = obj.prjname
            const curparent = that.$_.find(curPid, function (item) {
              return item.pid === parent
            })
            let open = true
            if (curparent) {
              dep = curparent.dep
              if (curparent.dep >= 2) open = false
            }
            if (obj.levelname !== '部件类型') {
              temp = arr2tree(data, data[i].id) // 递归调用
            }
            if (temp.length > 0) {
              // 如果找到了
              obj.children = temp // 父级的子集就等于刚才递归的结果
              obj.open = open
            } else {
              obj.children = [] // 没有子集就把这个父级的children字段改成null 防止出现收起展开的图标
            }
            tree.push(obj) // 把父级和子集放到最终输出
          }
        }
        return tree
      }
      let treeData = arr2tree(results[0].structures, null)
      return treeData
    },
    renderContent(h, { node, data, store }) {
      if (data.pressureType == '1') {
        return <span>{node.label}</span>
      } else if (data.pressureType == '2') {
        return <span style="color:#F4C545;">{node.label}</span>
      } else if (data.pressureType == '3') {
        return <span style="color:#00B983;">{node.label}</span>
      } else if (data.pressureType == '4') {
        return <span style="color:#FF4343;">{node.label}</span>
      } else {
        return <span>{node.label}</span>
      }
      //1未开工 2正在施工3已完工4停工
    },
    // 树结构子项点击调用
    handleNodeClick(data) {
      this.tipShow = false
      this.$emit('selectChange', data)
      //
      this.clearWall()
      if (data.code) this.pbsLocated(data)
      if (!window.viewer) return
      if (!data.longitude || !data.latitude) return
      const position = [Number(data.longitude), Number(data.latitude)]
      this.addSymbol(data, position)
      if (!data.range) return
      this.addWall(data, true)
    },
    addSymbol(data, position) {
      if (this.prjInfo) this.prjInfo.remove()
      const projectInfoConstructor = Vue.extend(ProjectInfo)
      this.prjInfo = new projectInfoConstructor({
        data: {
          info: data,
          isLocated: true,
          position
        },
        store: this.$store
      }).$mount()
    },
    addWall(data, isClick) {
      var that = this
      dataAssembly(JSON.parse(data.range).coordinates)
      function dataAssembly(range) {
        let resultArr = []
        for (let j = 0; j < range.length; j++) {
          //信息坐标获取
          const polygonArr = range[j].toString().split(',')
          //坐标数据转换为Number类型
          const turnNum = function (nums) {
            return nums.map(Number)
          }
          //坐标数据重新组装，加入高度
          const arrSlice = function (arr) {
            return arr.map((e, i) => (i % 2 ? null : [arr[i], arr[i + 1], 70.0])) // 两两取出
          }
          arrSlice(turnNum(polygonArr)).forEach((item) => {
            if (item !== null) {
              resultArr.push(item[0])
              resultArr.push(item[1])
              resultArr.push(item[2])
            }
          })
          //围墙展示
        }
        gradientWalls(resultArr, range)
      }
      function gradientWalls(potArray, range) {
        var alp = 1
        var num = 0
        var minHeights = []
        var maxHeights = []
        var fenceEntity = null
        for (let i = 0; i < potArray.length / 3; i++) {
          minHeights.push(potArray[i * 3 + 2])
        }
        for (let i = 0; i < potArray.length / 3; i++) {
          maxHeights.push(potArray[i * 3 + 2] + 400)
        }
        if (isClick) window.viewer.entities.removeById('dynamicWall')
        const newPositions = range.map((item) => {
          return Cesium.Cartesian3.fromDegrees(item[0], item[1])
        })
        const bound = Cesium.PolygonGeometry.computeRectangle({
          polygonHierarchy: new Cesium.PolygonHierarchy(newPositions)
        })
        const center = Cesium.Rectangle.center(bound)
        center.height = 200
        const centercar3 = Cesium.Cartographic.toCartesian(center)
        const color = 'rgb(56, 136, 205)'
        const canvas = document.createElement('canvas')
        canvas.width = 120
        canvas.height = 80
        const ctx = canvas.getContext('2d')
        const img = new Image()
        // img.src = require('@/assets/images/quantum/icon.png')
        // img.onload = () => {
        ctx.lineWidth = 10
        ctx.strokeStyle = color
        ctx.font = '18px bold 宋体'
        const width = ctx.measureText(data.name).width + 30
        canvas.width = width
        // ctx.drawImage(img, 0, 0, canvas.width, canvas.height)
        ctx.font = '18px bold 宋体'
        ctx.fillStyle = 'rgb(255,255,255)'
        ctx.textBaseline = 'middle'
        ctx.fillText(data.name, 15, 27)
        fenceEntity = window.viewer.entities.add({
          position: centercar3,
          id: isClick ? 'dynamicWall' : 'dynamicWall' + data.code,
          billboard: {
            sizeInMeters: false,
            image: canvas,
            heightReference: Cesium.HeightReference.RELATIVE_TO_GROUND,
            verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
            horizontalOrigin: Cesium.HorizontalOrigin.CENTER
          },
          wall: {
            positions: new Cesium.Cartesian3.fromDegreesArrayHeights(potArray), //fromDegreesArrayHeights    给定一个经度，纬度和高度值数组的笛卡尔坐标3位置数组，其中经度和纬度以度数表示。
            minimumHeights: minHeights,
            maximumHeights: maxHeights,
            material: new Cesium.ImageMaterialProperty({
              image: require('@/views/groupPage/images/jb02.png'),
              transparent: true,
              color: new Cesium.CallbackProperty(function () {
                if (num % 2 === 0) {
                  alp -= 0.05
                } else {
                  alp += 0.05
                }
                if (alp <= 0.3) {
                  num++
                } else if (alp >= 1) {
                  num++
                }
                return Cesium.Color.RED.withAlpha(alp) //new Cesium.Color(0.0, 0.0, 0.25, 0.8)
                //entity的颜色透明 并不影响材质，并且 entity也会透明
              }, false)
            })
          }
        })
        that.rangeSymbol = fenceEntity
        // }
        //聚焦定位
        // viewer.flyTo(fenceEntity)
      }
    },
    pbsLocated(data) {
      if (data !== null && data.layerName) {
        let lyName = '',
          code = data.value
        if (data.layerName.indexOf(',') > -1) {
          lyName = data.layerName.split(',')[1]
        } else {
          lyName = data.layerName
        }
        if (this.pipeInfo) {
          this.pipeInfo.close()
        }
        if (this.$store.state.bigScreen.currentPipeInfo) {
          this.$store.state.bigScreen.currentPipeInfo.close()
        }
        const pipeInfoConstructor = Vue.extend(PipeUnitInfo)
        this.pipeInfo = new pipeInfoConstructor({
          data: {
            isInteractive: false,
            locateUnit: {
              name: lyName,
              id: code
            }
          },
          store: this.$store
        }).$mount()
        this.$store.state.bigScreen.currentPipeInfo = this.pipeInfo
      }
    },
    //右键点击显示导出按钮
    exportQRCode(e, data) {
      this.treeNodeId = ''
      if (data !== null && data.levelname === '部件类型') {
        this.tipShow = false
        this.optionCardX = e.x
        this.optionCardY = e.y
        this.treeNodeId = data.id
        this.tipShow = true
      } else {
        this.tipShow = false
      }
    },
    //点击导出二维码
    async exportCurrent() {
      const downloadUrl = '/tofly-sxgk/commonFile/download'
      const data = { stdId: this.treeNodeId }
      let res = await createPdfByType_api(data)
      const { code, result } = res
      if (code === 1) {
        const pdf = this.$store.state.apiRoot + downloadUrl + '?fileName=' + result
        window.open(pdf)
        this.tipShow = false
      } else {
        this.$message.error('获取二维码信息失败')
      }
    },
    //设计模块的搜索
    searchOperation() {
      if (this.choke) return
      this.choke = true
      const code = this.searchInput.toString().trim()
      if (code === '') {
        this.$notify.error({
          title: '提示',
          message: '请输入查询内容',
          duration: 2500
        })
        return
      }
      const searchType = this.searchType.toString()
      switch (searchType) {
        case '0':
          this.searchOnline(code)
          break
        case '1':
          this.searchOnline(code)
          break
        case '2':
          this.searchLocal(code, true)
          break
      }
      setTimeout(() => {
        this.choke = false
      }, 4000)
    },
    //在线搜索，除工程名称外的2个选项使用
    searchOnline(value) {
      if (!value) return
      const size = 50 //每次最大搜索条数
      this.searchPBS(value, size)
    },
    //搜索功能
    async searchPBS(value, size) {
      let res = await pbsTreeSearch_api({
        prjId: this.prjId,
        pbs: value,
        pageSize: size
      })
      let { result, code } = res
      if (code === 1 && result) {
        if (result.length >= size) {
          this.$notify({
            title: '提示',
            message: `查询结果过多！当前显示匹配的${size}条结果`,
            type: 'warning',
            duration: 2000
          })
        }
        // 对搜索结果进行处理，让elementUI可以渲染
        const nodes = result.map((item) => {
          item.value = item.code
          item.name = `${item.pipeId}_${item.code}`
          item.leaf = true
          return item
        })
        this.treeData = nodes
      }
      this.$emit('searchCompleted')
    },
    /**
     * 工程名称选项本地搜索
     * code 模糊查询字符串
     * vague 是否模糊查询
     */
    searchLocal(code, vague) {
      let nodes = []
      let allNodes = this.originalData[0].structures //服务器原始数据目录
      let filterNodes = []
      if (vague) {
        //查找包含字符
        for (let i of allNodes) {
          if (i.originname) {
            if (i.originname.indexOf(code) != -1) {
              filterNodes.push(i)
            }
          }
        }
        //判断父子节点
        for (let i = 0; i < filterNodes.length; i++) {
          const item = filterNodes[i]
          const parentNode = _.find(filterNodes, (node) => {
            return node.id === item.pid
          })
          if (!parentNode) {
            nodes.push(item)
          }
        }
      }
      //显示查找结果
      this.treeData = nodes
    },
    //搜索类型改变时清空输入
    searchTypeChange() {
      this.searchInput = ''
    },
    //清除搜索结果
    clearInput() {
      this.treeData = this.fatherNodesData
    },
    //清除范围显示
    clearWall() {
      if (!window.viewer) return
      if (window.viewer.entities.getById('dynamicWall')) window.viewer.entities.removeById('dynamicWall')
    },
    //-----------------------------------------------------------------------------------------------------------------------外部调用
    async externalInit() {
      if (!window.viewer) return
      this.externalClear()
      pbsCustomDataSource = new Cesium.CustomDataSource('pbsCustomDataSource')
      window.viewer.dataSources.add(pbsCustomDataSource)
      let res = await getPbsListWithRange({ prjId: this.prjId })
      let { result, code } = res
      if (result.length == 0 || code != 1) return
      this.prjInfoArr = []
      result[0].structures.forEach((item) => {
        // if (item.code.match(/.\d{3}$/)) {
        if (item.longitude && item.latitude && item.positionShow === 1) {
          let icon = this.getProjectStatus(item.projectStatus)
          this.addIcon(item, icon)
        }
        // }
        // if (item.code.match(/\w{8}/)) {
        if (item.range) {
          if (item.rangeShow === 1) this.addRange(item)
        }
        // }
      })
      this.activeMapEvent()
    },
    //获取施工状态图标
    getProjectStatus(projectStatus) {
      let icon = null
      switch (projectStatus) {
        case '未开工':
          icon = require('@/views/groupPage/images/地图/未开工.png')
          break
        case '施工中':
          icon = require('@/views/groupPage/images/地图/施工中.png')
          break
        case '停工':
          icon = require('@/views/groupPage/images/地图/停工.png')
          break
        case '完工':
          icon = require('@/views/groupPage/images/地图/完工.png')
          break
        default:
          icon = require('@/views/groupPage/images/地图/未开工.png')
          break
      }
      return icon
    },
    //批量添加工程图标
    addIcon(data, icon) {
      const projectInfoConstructor = Vue.extend(ProjectInfo)
      const prjInfo = new projectInfoConstructor({
        data: {
          info: data,
          position: [data.longitude, data.latitude],
          icon
        },
        store: this.$store
      }).$mount()
      this.prjInfoArr.push(prjInfo)
    },
    //添加施工范围显示
    addRange(data) {
      let positions = JSON.parse(data.range).coordinates
      positions = positions.map((item) => {
        return Cesium.Cartesian3.fromDegrees(item[0], item[1])
      })
      let id = 'constructionRange' + data.code
      let entity = new Cesium.Entity({
        id: 'constructionRange' + data.code,
        info: data,
        type: 'constructionRange',
        polyline: {
          show: true,
          followSurface: false,
          clampToGround: true,
          positions: positions,
          material: Cesium.Color.CRIMSON,
          width: 2.0
        },
        polygon: {
          hierarchy: positions,
          material: Cesium.Color.RED.withAlpha(0),
          perPositionHeight: false,
          heightReference: Cesium.HeightReference.CLAMP_TO_GROUND
        }
      })
      if (!pbsCustomDataSource.entities.getById(id)) {
        pbsCustomDataSource.entities.add(entity)
      }
    },
    //激活地图事件
    activeMapEvent() {
      rangeHandler = new Cesium.ScreenSpaceEventHandler(window.viewer.canvas)
      // 设置要在输入事件上执行的功能，官方文档查询ScreenSpaceEventType可以看到所有的cesium鼠标事件
      rangeHandler.setInputAction((movement) => {
        var pickedObject = window.viewer.scene.pick(movement.position)
        this.clearRangeSymbol()
        if (this.$store.state.bigScreen.isClickingPipe) return
        if (
          window.viewer.scene.pickPositionSupported &&
          Cesium.defined(pickedObject) &&
          pickedObject.id.type == 'constructionRange'
        ) {
          setTimeout(() => {
            this.addWall(pickedObject.id.info, false)
          }, 100)
        }
      }, Cesium.ScreenSpaceEventType.LEFT_CLICK)
    },
    clearRangeSymbol() {
      if (this.rangeSymbol) {
        window.viewer.entities.remove(this.rangeSymbol)
        this.rangeSymbol = null
      }
    },
    //外部调用清除
    externalClear() {
      if (!window.viewer) return
      this.clearRangeSymbol()
      this.clearWall()
      if (Cesium.defined(pbsCustomDataSource)) {
        pbsCustomDataSource.entities.removeAll()
      }
      if (rangeHandler && !rangeHandler.isDestroyed()) {
        rangeHandler.destroy()
        rangeHandler = null
      }
      this.prjInfoArr.map((item) => {
        item.remove()
      })
    }
  },
  beforeDestroy() {
    if (window.viewer) {
      this.clearWall()
      if (this.prjInfo) this.prjInfo.remove()
      // if (this.pipeInfo) this.pipeInfo.close()
    }
  }
}
</script>
<style lang="scss" scoped>
.widget-pbsTreeManagement {
  width: 100%;
  height: 100%;
  padding: 0 !important;
  .designSearch {
    display: flex;
    .designItem {
      // margin: 0 5px;
      /deep/.el-input-group__append {
        // background-color: #1d5987;
        background-color: #093054;
        border: none;
        color: #2ba7ff;
      }
    }
  }
  .designTree {
    height: calc(100% - 0.260417rem /* 50/192 */);
    overflow-y: auto;
    margin-top: 10px;
    position: relative;
    .tip {
      position: fixed;
      z-index: 999;
      width: 50px;
    }
  }
  @import './common.scss';
}
</style>