function buildTdtTileUrl(id, tk) {
  return `${location.origin}/api/tdt/cache/${id}/{z}/{y}/{x}/${tk}?v=2022`
}

/**
 * 经纬度坐标拾取控件
 */
class GeolocateInfoControl {
  toText(lngLat) {
    return '经度：' + lngLat.lng.toFixed(6) + ', 纬度：' + lngLat.lat.toFixed(6)
  }

  onAdd(map) {
    this.map = map
    this.container = document.createElement('div')
    this.container.className = 'mapboxgl-ctrl mapboxgl-ctrl-lnglat'
    this.container.textContent = this.toText(map.getCenter())

    // 鼠标移动，显示经纬度信息
    map.on('mousemove', e => {
      const element = this.container
      element.textContent = this.toText(e.lngLat)
    })

    // 创建一个 Marker 实例
    const popup = new mapboxgl.Popup({ offset: 25, closeOnClick: false, closeButton: false })
      .setLngLat(map.getCenter())
      .setText(this.toText(map.getCenter()))
      .addTo(map)
    const marker = new mapboxgl.Marker().setLngLat(map.getCenter()).addTo(map)

    // 创建一个存储经纬度的容器，用于复制功能
    const textarea = document.createElement('textarea')
    textarea.id = 'geolocate-info'
    document.body.appendChild(textarea)

    // 监听地图点击事件，复制经纬度
    map.on('click', e => {
      const lonlat = this.toText(e.lngLat)

      // 更新 marker 的位置
      popup.setLngLat(e.lngLat).setText(lonlat)
      marker.setLngLat(e.lngLat)

      // 更新 textarea 的内容
      textarea.textContent = lonlat.replace('经度：', '').replace('纬度：', '')
      textarea.select()
      // 执行复制命令
      document.execCommand('Copy')
    })

    return this.container
  }

  onRemove() {
    this.container.parentNode.removeChild(this.container)
    this.map = undefined
  }
}

/**
 * 图层控件
 * 目前仅支持天地图图层
 */
class LayerControl {
  constructor(options) {
    this.tk = options.tk
    this.layers = options.layers
  }

  onAdd(map) {
    this.map = map
    this.container = document.createElement('div')
    this.container.className = 'mapboxgl-ctrl mapboxgl-ctrl-group mapbox-control'

    const layersWrapHtml = []
    if (this.layers) {
      layersWrapHtml.push('<div class="mapboxgl-ctrl-layer-wrap">')
      this.layers.forEach(layer => {
        layersWrapHtml.push(`
                  <div class="mapboxgl-ctrl-layer ${
                    layer.active ? 'active' : ''
                  }" data-layer-ids="${layer.value}">
                      <img src="${layer.image}" alt="${layer.label}" />
                      <span>${layer.label}</span>
                  </div>
              `)

        for (const id of layer.value.split(',')) {
          map.addLayer(
            {
              id: 't_' + id,
              type: 'raster',
              source: {
                type: 'raster',
                tiles: [buildTdtTileUrl(id, this.tk)],
                tileSize: 256,
                maxzoom: 18
              },
              layout: { visibility: layer.active ? 'visible' : 'none' }
            },
            'background'
          )
        }
      })
      layersWrapHtml.push('</div>')
    }

    this.container.innerHTML = `
          <button type="button" class="mapboxgl-ctrl-layer-button" title="地图样式选择">
            <span class="mapboxgl-ctrl-icon" aria-hidden="true" title="Layer"></span>
              ${layersWrapHtml.join('')}
          </button>
      `
    this.container.addEventListener('click', e => {
      const target = e.target
      const parent = target.parentElement
      if (parent.classList.contains('mapboxgl-ctrl-layer')) {
        const ids = parent.getAttribute('data-layer-ids')
        const list = parent.parentElement.children
        for (let i = 0; i < list.length; i++) {
          const item = list[i]
          if (item.classList.contains('mapboxgl-ctrl-layer')) {
            if (item.getAttribute('data-layer-ids') === ids) {
              item.classList.toggle('active')
            } else {
              item.classList.remove('active')
            }
          }
        }

        this.layers.forEach(layer => {
          for (const id of layer.value.split(',')) {
            map.setLayoutProperty(`t_${id}`, 'visibility', 'none')
          }
        })
        if (parent.classList.contains('active')) {
          for (const id of ids.split(',')) {
            map.setLayoutProperty(`t_${id}`, 'visibility', 'visible')
          }
        }
        return
      }

      this.container.querySelector('button').classList.toggle('-active')
    })

    return this.container
  }

  onRemove() {
    this.container.parentNode.removeChild(this.container)
    this.map = undefined
  }
}
