<template>
  <div>
    <div class="search-box">
      <el-button v-if="$route.query?.type=='init'" type="primary" style="margin-right:10px;" @click="toggleShowCard">地址取点</el-button>
      <input id="tipinput" v-model="searchValue" placeholder="请输入搜索地址" class="input-with-select" @keyup.enter="getSingleAddressDetail({address: searchValue})">
      <el-button v-if="$route.query?.type=='init'" v-loading="gettingAddr" type="primary" @click="editMaps">自定义围点</el-button>
      <el-button v-if="$route.query?.type=='init'" type="primary" @click="clearGraphics">清除围点</el-button>
      <el-button v-if="$route.query.type === 'init' || $route.query.type === 'edit'" type="primary" @click="submitPoly">提交</el-button>
      <el-card v-show="showAddrCard" class="addr-card">
        <el-button type="primary" size="small" @click="addressList.push({address:''})">增加范围</el-button>
        <!-- <p class="tips">地址的门牌号范围请用“~”号分隔</p> -->
        <ul>
          <li v-for="(each, index) in addressList" :key="'addressList'+index" class="addr">
            <el-input v-model="each.address" placeholder="请输入详细地址或地址范围" class="el-addr" @keyup.enter.native="getSingleAddressDetail(each)">
              <el-button slot="append" type="primary" icon="el-icon-map-location" @click="getSingleAddressDetail(each)" />
            </el-input>
            <el-button type="danger" size="mini" class="remove" @click="removeAddress(index)">-</el-button>
          </li>
        </ul>
        <div class="btn-box">
          <el-button v-loading="gettingAddr" type="primary" size="small" @click="createPolygonByAddress">创建地址围点</el-button>
        </div>
      </el-card>
    </div>
    <div id="viewDiv" class="viewDiv " />
  </div>
</template>

<script>
import WebMap from '@geoscene/core/WebMap'
import MapView from '@geoscene/core/views/MapView.js'
import Graphic from '@geoscene/core/Graphic.js'
import SimpleFillSymbol from '@geoscene/core/symbols/SimpleFillSymbol.js'
import Polygon from '@geoscene/core/geometry/Polygon'
import * as locator from '@geoscene/core/rest/locator.js'
import Sketch from '@geoscene/core/widgets/Sketch.js'
import SketchViewModel from '@geoscene/core/widgets/Sketch/SketchViewModel'
import GraphicsLayer from '@geoscene/core/layers/GraphicsLayer.js'
import { saveSlicePolygon, getSlicePolygon } from '@/api/areaSlice'
import Point from '@geoscene/core/geometry/Point.js'
import * as webMercatorUtils from '@geoscene/core/geometry/support/webMercatorUtils'
export default {
  data() {
    return {
      loading: true,
      geosceneMap: null, // 地图
      geosceneView: null, // 视图
      searchValue: '',
      searchResult: [],
      graphicsLayer: null, // 图层
      showAddrCard: false,
      gettingAddr: false,
      map: null,
      addressList: [{ address: '' }],
      paths: [],
      actualPath: [],
      mapList: [],
      currenLngLat: [],
      geocoder: null,
      curMarker: null,
      dMenu: null, // 清除片区的菜单
      pMenu: null, // 路段锚点右键菜单
      sketchViewModel: null, // 图层，
      selectedGraphic: null,
      drawingActive: false,
      graphicsCount: 0,
      symbolStyle: {
        color: 'rgba(226, 225, 220, 0.3)',
        type: 'simple-fill',
        outline: {
          color: '#323232',
          width: 2
        }
      },
      webMercatorUtils: null
    }
  },
  created() {

  },
  mounted() {
    this.webMercatorUtils = webMercatorUtils
    // 状态初始化
    if (this.$route.query.type === 'edit') {
      getSlicePolygon(this.$route.query.id).then(res => {
        if (res.data && res.data.length > 0) {
          res.data.forEach(each => {
            this.paths.push([each.lng, each.lat])
          })
          this.actualPath = this.getActualPath(this.paths)
        }
      }).catch(() => {
      })
    }
    this.createMap()
  },
  methods: {
    async createMap() {
      this.geosceneMap = new WebMap({
        basemap: 'tianditu-vector' // 底图图层服务,
      })

      this.geosceneView = new MapView({
        map: this.geosceneMap,
        center: [113.264, 23.129], // 经度，纬度
        zoom: 14, // 缩放级别
        container: 'viewDiv', // Div 元素,
        constraints: {
          minZoom: 10, // 最小缩放级别
          maxZoom: 18 // 最大缩放级别
        }
      })
      this.graphicsLayer = new GraphicsLayer()
      this.geosceneMap.add(this.graphicsLayer)
      // 初始化 SketchViewModel 用于编辑
      this.sketchViewModel = new SketchViewModel({
        view: this.geosceneView,
        layer: this.graphicsLayer,
        updateOnGraphicClick: true,
        defaultUpdateOptions: {
          enableRotation: true,
          enableScaling: true
        }
      })
      this.sketchViewModel.on('update', (event) => {
        if (event.state === 'complete') {
          const geometry = event.graphics[0].geometry
          let data = {}
          if (geometry.spatialReference.isWebMercator) {
            data = this.webMercatorUtils.webMercatorToGeographic(geometry)
          }
          this.actualPath = this.getActualPath(data.rings[0])
        }
      })
      // 地图加载完成后执行
      await this.geosceneMap.when(() => {
        // 设置事件监听
        if (this.$route.query.type === 'edit') {
          this.addSamplePolygon()
        }
      })
    },
    addSamplePolygon() {
      // const dataArr = this.sortPoints(this.paths)
      this.paths = [
        [113.25902653521703, 23.14261467975728],
        [113.26155869004808, 23.135981311416966],
        [113.27079096421619, 23.149985131990622]
      ]
      const polygon = new Polygon({
        rings: this.paths,
        // [
        //   [113.25902653521703, 23.14261467975728],
        //   [113.26155869004808, 23.135981311416966],
        //   [113.27079096421619, 23.149985131990622]
        // ],
        spatialReference: { wkid: 4326 }
      })
      const graphic = new Graphic({
        geometry: polygon,
        symbol: this.symbolStyle
      })
      this.graphicsLayer.add(graphic)
    },
    async getSingleAddressDetail(item) {
      if (!item && item === '') {
        this.$message.warning('请输入搜索地址')
        return
      }
      try {
        const locatorUrl = 'https://www.geosceneonline.cn/geocode/rest/GeoScene/GeocodeServer'
        const response = await locator.addressToLocations(locatorUrl, {
          maxLocations: 25,
          address: {
            SingleLine: item.address
          }
        })
        this.searchResult = response.map(item => ({
          address: item.address,
          location: item.location,
          extent: item.extent,
          attributes: item.attributes
        }))

        // 如果有结果，定位到第一个结果
        if (this.searchResult.length > 0) {
          this.zoomToResult(this.searchResult[0])
        } else {
          this.$message.warning('未找到匹配的地址')
        }
      } catch (error) {
        this.$message.error('地址搜索失败，请稍后重试')
      }
    },
    clearGraphics() {
      if (this.graphicsLayer) {
        this.graphicsLayer.removeAll()
      }
      if (this.geosceneView) {
        this.geosceneView.graphics.removeAll()
      }
    },
    // 创建地址围点
    createPolygonByAddress() {
      if (this.gettingAddr) return
      let flag = false
      for (const i in this.addressList) {
        flag = this.$util.isNotEmpty(this.addressList[i].address) | flag
      }
      if (!flag) {
        return this.$message.info('请先输入地址范围')
      }
      let info = '是否确认进行地址围点的创建'
      const _this = this
      if (_this.paths) {
        info = '是否确认清除已画围点，并进行地址围点的创建？'
      }
      _this.$confirm(info).then(_ => {
        _this.paths = []
        _this.geosceneView.graphics.removeAll()
        if (this.graphicsLayer) {
          this.graphicsLayer.removeAll()
        }
        if (_this.addressList.length < 3) {
          _this.$message.warning('请输入三个或三个以上详细地址进行围点')
        } else {
          this.gettingAddr = true
          for (const i in _this.addressList) {
            if (_this.$util.isNotEmpty(_this.addressList[i].address)) {
              _this.getAddressCode(_this.addressList[i])
              _this.gettingAddr = false
            }
          }
          this.graphicsLayer = new GraphicsLayer()
          setTimeout(() => {
            this.gettingAddr = true
            const dataArr = _this.sortPoints(_this.paths)
            this.actualPath = _this.getActualPath(dataArr) // 把获取到的经纬度处理成一维数组
            const polygon = new Polygon({
              rings: dataArr, // 闭合环
              spatialReference: { wkid: 4326 } // WGS84坐标系
            })
            // 创建覆盖物
            const polylineSymbol = new SimpleFillSymbol({
              color: 'rgba(226, 225, 220, 0.3)',
              outline: {
                color: '#323232',
                width: 2
              }
            })
            const polylineGraphic = new Graphic({
              geometry: polygon,
              symbol: polylineSymbol,
              layer: this.graphicsLayer
            })
            this.geosceneView.graphics.add(polylineGraphic)
            _this.gettingAddr = false
          }, 2000)
        }
      }).catch(_ => {})
    },
    toggleShowCard() {
      this.showAddrCard = !this.showAddrCard
    },
    getActualPath(arr) {
      if (arr) {
        const newPath = []
        arr.forEach((item) => {
          newPath.push(item.join(','))
        })
        return newPath
      }
    },
    // 计算中心点
    calculateCenter(points) {
      let sumLng = 0
      let sumLat = 0

      for (const point of points) {
        sumLng += point[0]
        sumLat += point[1]
      }
      return [sumLng / points.length, sumLat / points.length]
    },
    // 极角排序函数
    sortPoints(points) {
      if (points.length < 3) return points
      // 计算中心点
      const center = this.calculateCenter(points)
      // 复制点集并排序
      return points.slice().sort((a, b) => {
        const angleA = Math.atan2(a[1] - center[1], a[0] - center[0])
        const angleB = Math.atan2(b[1] - center[1], b[0] - center[0])
        // 如果角度相同，按距离排序
        if (angleA === angleB) {
          const distA = Math.pow(a[0] - center[0], 2) + Math.pow(a[1] - center[1], 2)
          const distB = Math.pow(b[0] - center[0], 2) + Math.pow(b[1] - center[1], 2)
          return distA - distB
        }

        return angleA - angleB
      })
    },
    // 删除地址
    removeAddress(index) {
      const addressInfo = this.addressList.splice(index, 1)
      const markerList = addressInfo[0].markerList
      if (markerList) {
        markerList.forEach(each => {
          this.map.remove(each)
        })
      }
    },

    editMaps() {
      this.$confirm('如有已选围点，此操作将清除已有围点, 是否继续?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        this.showAddrCard = false
        this.addressList = [{ address: '' }]
        this.geosceneView.graphics.removeAll()
        this.actualPath = []
        this.graphicsLayer = new GraphicsLayer()
        this.geosceneMap.add(this.graphicsLayer)
        const sketch = new Sketch({
          layer: this.graphicsLayer,
          view: this.geosceneView,
          creationMode: 'single'
        })
        sketch.create('polygon')
        const _this = this
        sketch.on('create', function(event) {
          if (event.state === 'complete') {
            _this.actualPath = _this.getActualPath(event.graphic.geometry.rings)
          }
        })
      }).catch(() => {
        this.$message({
          type: 'info',
          message: '已取消删除'
        })
      })
    },
    getAddressCode(addressItem) {
      const locatorUrl = 'https://www.geosceneonline.cn/geocode/rest/GeoScene/GeocodeServer'
      locator.addressToLocations(locatorUrl, {
        maxLocations: 25,
        address: {
          SingleLine: addressItem.address
        },
        outFields: ['*']
      }).then((results) => {
        results.forEach((result) => {
          this.paths.push([result.location.longitude, result.location.latitude])
        })
      })
    },
    // 提交
    submitPoly() {
      if (this.actualPath.length <= 0) {
        this.$message.warning('请先选取区域')
        return
      }
      this.$confirm('是否确认提交该片区围点信息？', '确认提交', {
        beforeClose: (action, instance, done) => {
          if (action === 'confirm') {
            instance.confirmButtonLoading = true
            const data = {
              sliceId: this.$route.query.id,
              pointList: this.actualPath
            }
            saveSlicePolygon(data).then(res => {
              if (res.code === 0) {
                this.$message.success('保存成功')
                instance.confirmButtonLoading = false
                done()
                this.$router.replace({ path: '/system/slice/map', query: {
                  ...this.$route.query,
                  type: 'edit'
                }})
                if (window.opener && window.opener.loadPage) {
                  window.opener.loadPage()
                }
              } else {
                this.$message.error('保存失败，' + res.msg)
              }
            })
            setTimeout(() => {
              instance.confirmButtonLoading = false
              done()
            }, 3000)
          } else if (!instance.confirmButtonLoading) {
            done()
          }
        }
      })
    },
    // 按照经纬度定位并标志
    async zoomToResult(result) {
      // if (this.graphicsLayer) {
      //   this.graphicsLayer.removeAll()
      // }
      // this.geosceneView.graphics.removeAll()
      // 创建标记符号
      const symbol = {
        type: 'simple-marker',
        style: 'triangle',
        color: 'red',
        size: '20px', // pixels
        outline: {
          color: 'red',
          width: 0
        }
      }

      // 创建点图形
      const point = new Point({
        x: result.location.x,
        y: result.location.y,
        spatialReference: {
          wkid: 4326
        }
      })
      const graphic = new Graphic({
        geometry: point,
        symbol: symbol
      })
      this.geosceneView.graphics.add(graphic)

      // 定位到结果
      if (result.extent) {
        this.geosceneView.goTo({
          target: result.extent,
          zoom: 16
        })
      } else {
        this.geosceneView.goTo({
          target: point,
          zoom: 16
        })
      }
    }
  }
}
</script>

<style scoped lang="scss">
.viewDiv {
  /* padding: 0;
  margin: 0; */
  height: 100vh;
  width: 100%;
}
.search-box{
  position:fixed;
  top:55px;
  right:160px;
  z-index:9999;
  input{
    height:35px;
    padding:7px;
  }
  .input-with-select {
    margin-right: 10px;
  }
  .addr-card{
    min-width:355px;
    max-height: 300px;
    overflow-y: scroll;
    ul{
      list-style:none;
      padding-inline-start:0;
      li.addr{
        .el-addr{
          width:calc(100% - 45px)
        }
        .remove{
          margin-left:5px;
        }
      }
    }
    .tips{
      color:grey;
      font-size:12px;
    }
  }
}
</style>
<style>
@import 'https://js.geoscene.cn/4.25/@geoscene/core/assets/geoscene/themes/dark/main.css';
</style>

