import mapboxgl from 'mapbox-gl'
import MapboxDraw from '@mapbox/mapbox-gl-draw'
import '@mapbox/mapbox-gl-draw/dist/mapbox-gl-draw.css'
import { setNoflyData, setRestrictflyData } from '@/utils/api/table'
import { Message, MessageBox } from 'element-ui'

/**
 * 自定义地图样式切换控件
 * 用于在 Mapbox 地图上添加一个控件，允许用户选择不同的地图样式
 */
export class MapboxStyleSwitcherControl {
  /**
   * 构造函数
   * @param {Array} styles - 可选的样式列表，每个样式包含 name 和 URI。默认为空数组。
   * @param {String} defaultIconClass - 自定义图标的 CSS 类名。默认为空字符串。
   * @param {Number} currentStyleIndex - 当前选中的样式索引。默认为 0。
   */
  constructor (styles = [], defaultIconClass = '', currentStyleIndex = 0) {
    this.styles = styles
    this.defaultIconClass = defaultIconClass
    this.currentStyleIndex = currentStyleIndex // 当前样式索引
    this.controlContainer = null // 控件容器
    this.map = null // 地图实例
    this.styleButton = null // 切换样式的按钮
    this.styleDropdown = null // 样式选择的下拉菜单
  }

  /**
   * 添加控件到地图上
   * @param {MapboxMap} map - Mapbox 地图实例
   * @returns {HTMLElement} 控件的容器元素
   */
  onAdd (map) {
    this.map = map

    // 创建控件的容器元素
    this.controlContainer = document.createElement('div')
    this.controlContainer.className = 'mapboxgl-ctrl mapboxgl-ctrl-group'
    this.controlContainer.style.display = 'flex'
    this.controlContainer.style.flexDirection = 'column'
    this.controlContainer.style.alignItems = 'center'
    this.controlContainer.style.justifyContent = 'center'
    this.controlContainer.style.overflow = 'hidden'

    // 创建切换样式的按钮
    this.styleButton = document.createElement('button')
    this.styleButton.className = this.defaultIconClass || 'style-switcher-button' // 如果提供了自定义类名，则使用它
    this.styleButton.onclick = this._toggleDropdown.bind(this) // 绑定按钮点击事件

    // 让按钮内容（图标）居中
    this.styleButton.style.display = 'flex'
    this.styleButton.style.alignItems = 'center'
    this.styleButton.style.justifyContent = 'center'
    this.styleButton.style.width = '29px' // 可以根据需要调整
    this.styleButton.style.height = '29px' // 可以根据需要调整

    // 创建样式选择的下拉菜单
    this.styleDropdown = document.createElement('div')
    this.styleDropdown.className = 'style-dropdown'
    this.styleDropdown.style.display = 'none' // 初始状态为隐藏
    this.styleDropdown.style.cursor = 'pointer' // 鼠标样式

    // 为每个样式创建选择项并添加到下拉菜单中
    this.styles.forEach((style, index) => {
      const styleOption = document.createElement('div')
      styleOption.className = 'style-option'
      styleOption.innerHTML = style.name // 使用 name 作为显示内容
      styleOption.style.padding = '5px 5px'
      styleOption.style.borderTop = '1px solid #ddd'
      styleOption.style.overflow = 'hidden'
      // 如果当前样式索引与选中样式索引匹配，添加高亮样式
      if (this.currentStyleIndex === index) {
        styleOption.style.color = '#409EFF' // 设置选中项字体颜色
      } else {
        styleOption.style.color = 'black' // 设置默认字体颜色
      }
      styleOption.onclick = () => this._changeStyle(style, index) // 绑定样式选择事件

      // 添加鼠标经过效果
      styleOption.addEventListener('mouseover', () => {
        styleOption.style.backgroundColor = '#f0f0f0' // 鼠标经过时的背景颜色
      })

      styleOption.addEventListener('mouseout', () => {
        styleOption.style.backgroundColor = 'transparent' // 鼠标移开时的背景颜色
      })

      this.styleDropdown.appendChild(styleOption)
    })

    // 将按钮和下拉菜单添加到控件容器中
    this.controlContainer.appendChild(this.styleButton)
    this.controlContainer.appendChild(this.styleDropdown)

    return this.controlContainer
  }

  /**
   * 从地图上移除控件
   */
  onRemove () {
    this.controlContainer.parentNode.removeChild(this.controlContainer)
    this.map = null
  }

  /**
   * 切换下拉菜单的显示状态
   */
  _toggleDropdown () {
    if (this.styleDropdown.style.display === 'none') {
      this.styleDropdown.style.display = 'block' // 显示下拉菜单
      this.styleButton.style.width = '100%' // 可以根据需要调整
    } else {
      this.styleDropdown.style.display = 'none' // 隐藏下拉菜单
      this.styleButton.style.width = '29px' // 可以根据需要调整
    }
  }

  /**
   * 切换地图样式
   * @param {Object} style - 要切换到的样式对象
   * @param {Number} index - 要切换到的样式索引
   */
  _changeStyle (style, index) {
    this.map.setStyle(style) // 设置地图样式
    this.styleDropdown.style.display = 'none' // 隐藏下拉菜单
    this.styleButton.style.width = '29px' // 可以根据需要调整
    this.currentStyleIndex = index // 更新当前选中的样式索引
    this._updateStyleOptions() // 更新下拉菜单中的样式选项
  }

  /**
   * 更新下拉菜单中的样式选项
   */
  _updateStyleOptions () {
    const styleOptions = this.styleDropdown.querySelectorAll('.style-option')
    styleOptions.forEach((option, index) => {
      if (this.currentStyleIndex === index) {
        option.style.color = '#409EFF' // 高亮选中项
      } else {
        option.style.color = 'black' // 默认字体颜色
      }
    })
  }
}

// 飞机跟随控件
export class FollowControl {
  constructor ({ defaultIconClass, activeIconClass, onClick }) {
    this._defaultIconClass = defaultIconClass
    this._activeIconClass = activeIconClass
    this._onClick = onClick
    this._isActive = false // 控件是否激活的状态
  }

  onAdd (map) {
    this._map = map
    this._container = document.createElement('div')
    this._container.className = 'mapboxgl-ctrl mapboxgl-ctrl-group'

    this._button = document.createElement('button')
    this._button.className = this._defaultIconClass // 初始化时使用默认图标
    this._button.onclick = this._handleClick.bind(this) // 绑定点击事件处理函数

    this._container.appendChild(this._button)

    // 监听地图 mousedown 事件
    this._map.on('mousedown', this._handleMapMouseDown.bind(this))

    // 监听触摸事件
    this._map.getCanvasContainer().addEventListener('touchstart', this._handleMapMouseDown.bind(this))
    this._map.getCanvasContainer().addEventListener('touchmove', this._handleMapMouseDown.bind(this))
    this._map.getCanvasContainer().addEventListener('touchend', this._handleMapMouseDown.bind(this))

    return this._container
  }

  _handleClick () {
    this._isActive = !this._isActive
    this._button.className = this._isActive
      ? this._activeIconClass
      : this._defaultIconClass

    // 执行传入的点击回调函数
    if (this._onClick) {
      this._onClick(this._isActive) // 传递控件的当前激活状态
    }
  }

  _handleMapMouseDown () {
    if (this._isActive) {
      this._isActive = false
      this._button.className = this._defaultIconClass

      if (this._onClick) {
        this._onClick(false) // 停止跟随
      }
    }
  }

  onRemove () {
    this._map.off('mousedown', this._handleMapMouseDown.bind(this))
    this._container.parentNode.removeChild(this._container)
    this._map = undefined
  }
}

// 全屏控制控件 ps:官方全屏子类 添加一个回调
export class CustomFullscreenControl extends mapboxgl.FullscreenControl {
  constructor (handleResize) {
    super()
    this.handleResize = handleResize
  }

  _onClickFullscreen () {
    super._onClickFullscreen() // 调用原始的全屏切换行为
    this.handleResize() // 调用自定义的 handleResize 方法
  }
}

// 禁飞区控件类
export class NoFlyControl {
  constructor (options = {}) {
    this._map = null // 地图实例
    this._container = null // 控件容器（用于放按钮）
    this._draw = null // MapboxDraw 实例
    this._onDrawFinish = options.onDrawFinish || function () {} // 绘制完成时的回调
    this._defaultPolygons = options.defaultPolygons || [] // 初始加载的禁飞区多边形坐标
    this._onSave = options.onSave || function () {} // 保存时的回调
    this._shopId = options.shopId // 商户ID，用于提交接口
  }

  // 当控件添加到地图上时调用
  onAdd (map) {
    this._map = map

    // 创建控件按钮容器
    this._container = document.createElement('div')
    this._container.className = 'mapboxgl-ctrl mapboxgl-ctrl-group'

    // --- 绘制按钮 ---
    const drawButton = document.createElement('button')
    drawButton.className = 'mapboxgl-ctrl-icon'
    drawButton.type = 'button'
    drawButton.innerHTML = '✏️' // 图标：铅笔
    drawButton.title = '绘制禁飞区' // 鼠标提示
    drawButton.onclick = () => this._enableDraw() // 点击启用绘制模式
    this._container.appendChild(drawButton)

    // --- 保存按钮 ---
    const saveButton = document.createElement('button')
    saveButton.className = 'mapboxgl-ctrl-icon'
    saveButton.type = 'button'
    saveButton.innerHTML = '💾' // 图标：磁盘
    saveButton.title = '保存禁飞区'
    saveButton.onclick = () => this._savePolygons()
    this._container.appendChild(saveButton)

    // --- 删除按钮（删除选中图形） ---
    const deleteButton = document.createElement('button')
    deleteButton.className = 'mapboxgl-ctrl-icon'
    deleteButton.type = 'button'
    deleteButton.innerHTML = '🗑️'
    deleteButton.title = '删除选中图形'
    deleteButton.onclick = () => this._deleteSelected()
    this._container.appendChild(deleteButton)

    // --- 初始化 MapboxDraw 控件 ---
    this._draw = new MapboxDraw({
      displayControlsDefault: false, // 不显示默认工具条
      styles: [ // 自定义绘制样式（橙色）
        {
          id: 'gl-draw-polygon-fill',
          type: 'fill',
          filter: ['all', ['==', '$type', 'Polygon'], ['!=', 'mode', 'static']],
          paint: {
            'fill-color': '#f33', // 填充颜色
            'fill-opacity': 0.3 // 透明度
          }
        },
        {
          id: 'gl-draw-polygon-stroke-active',
          type: 'line',
          filter: ['all', ['==', '$type', 'Polygon'], ['!=', 'mode', 'static']],
          paint: {
            'line-color': '#f33', // 边框颜色
            'line-width': 2
          }
        },
        // 控制点外圈（白色光晕）
        {
          id: 'gl-draw-polygon-and-line-vertex-halo-active',
          type: 'circle',
          filter: ['all', ['==', 'meta', 'vertex'], ['==', '$type', 'Point']],
          paint: {
            'circle-radius': 7,
            'circle-color': '#fff'
          }
        },
        // 控制点内圈
        {
          id: 'gl-draw-polygon-and-line-vertex-active',
          type: 'circle',
          filter: ['all', ['==', 'meta', 'vertex'], ['==', '$type', 'Point']],
          paint: {
            'circle-radius': 5,
            'circle-color': '#fff'
          }
        }
      ]
    })

    // 将 Draw 控件添加到地图上
    map.addControl(this._draw)

    // --- 加载已有禁飞区（回显数据） ---
    if (this._defaultPolygons.length > 0) {
      const features = this._defaultPolygons.map(coords => ({
        type: 'Feature',
        geometry: {
          type: 'Polygon',
          coordinates: [coords] // 注意：GeoJSON Polygon 外层需要再包一层
        },
        properties: {}
      }))
      this._draw.set({
        type: 'FeatureCollection',
        features
      })
    }

    // 监听绘制完成事件
    map.on('draw.create', this._handleDraw.bind(this))

    return this._container
  }

  // 当控件被移除时执行
  onRemove () {
    if (this._map && this._draw) {
      this._map.removeControl(this._draw)
    }
    if (this._container?.parentNode) {
      this._container.parentNode.removeChild(this._container)
    }
    this._map = null
  }

  // 启用多边形绘制模式
  _enableDraw () {
    if (this._draw && this._map) {
      this._draw.changeMode('draw_polygon')
    }
  }

  // 绘制完成的处理函数
  _handleDraw (e) {
    const features = this._draw.getAll()
    if (features.features.length > 0) {
      const coordinates = features.features.map(f => f.geometry.coordinates)
      this._onDrawFinish(coordinates) // 通知外部最新绘制结果
    }
  }

  // 删除当前选中的图形
  _deleteSelected () {
    if (this._draw) {
      const selected = this._draw.getSelectedIds()
      if (selected.length > 0) {
        this._draw.delete(selected)
      }
    }
  }

  // 提交所有禁飞区数据到服务器
  async _savePolygons () {
    if (!this._draw) return

    const allFeatures = this._draw.getAll()

    // 提取所有 Polygon 类型图形的坐标（只取外环）
    const polygons = allFeatures.features
      .filter(f => f.geometry.type === 'Polygon')
      .map(f => f.geometry.coordinates[0])

    try {
      const shopId = this._shopId
      await setNoflyData(shopId, polygons)
    } catch (error) {
      Message.error('上传禁飞区数据时发生错误')
      console.error(error)
    }

    // 调用保存成功回调
    this._onSave(polygons)
  }
}

// 限飞区控件类
export class RestrictflyControl {
  constructor (options = {}) {
    this._map = null
    this._container = null
    this._draw = null
    this._shopId = options.shopId
    this._defaultPolygons = options.defaultPolygons || []
    this._defaultHeights = options.defaultHeights || []
    this._restrictflyHeights = [] // 保存限高值
    this._onSave = options.onSave || function () {}
  }

  onAdd (map) {
    this._map = map

    this._container = document.createElement('div')
    this._container.className = 'mapboxgl-ctrl mapboxgl-ctrl-group'

    // 绘制按钮
    const drawButton = document.createElement('button')
    drawButton.className = 'mapboxgl-ctrl-icon'
    drawButton.type = 'button'
    drawButton.innerHTML = '✏️'
    drawButton.title = '绘制限飞区'
    drawButton.onclick = () => this._enableDraw()
    this._container.appendChild(drawButton)

    // 保存按钮
    const saveButton = document.createElement('button')
    saveButton.className = 'mapboxgl-ctrl-icon'
    saveButton.type = 'button'
    saveButton.innerHTML = '💾'
    saveButton.title = '保存限飞区'
    saveButton.onclick = () => this._savePolygons()
    this._container.appendChild(saveButton)

    // 删除按钮
    const deleteButton = document.createElement('button')
    deleteButton.className = 'mapboxgl-ctrl-icon'
    deleteButton.type = 'button'
    deleteButton.innerHTML = '🗑️'
    deleteButton.title = '删除选中图形'
    deleteButton.onclick = () => this._deleteSelected()
    this._container.appendChild(deleteButton)

    // 初始化 MapboxDraw 控件（橙色样式）
    this._draw = new MapboxDraw({
      displayControlsDefault: false,
      styles: [
        {
          id: 'gl-draw-polygon-fill',
          type: 'fill',
          filter: ['all', ['==', '$type', 'Polygon'], ['!=', 'mode', 'static']],
          paint: {
            'fill-color': '#f83',
            'fill-opacity': 0.3
          }
        },
        {
          id: 'gl-draw-polygon-stroke-active',
          type: 'line',
          filter: ['all', ['==', '$type', 'Polygon'], ['!=', 'mode', 'static']],
          paint: {
            'line-color': '#f83',
            'line-width': 2
          }
        },
        {
          id: 'gl-draw-polygon-and-line-vertex-halo-active',
          type: 'circle',
          filter: ['all', ['==', 'meta', 'vertex'], ['==', '$type', 'Point']],
          paint: {
            'circle-radius': 7,
            'circle-color': '#fff'
          }
        },
        {
          id: 'gl-draw-polygon-and-line-vertex-active',
          type: 'circle',
          filter: ['all', ['==', 'meta', 'vertex'], ['==', '$type', 'Point']],
          paint: {
            'circle-radius': 5,
            'circle-color': '#fff'
          }
        }
      ]
    })

    map.addControl(this._draw)

    // 回显已有限飞区
    if (this._defaultPolygons.length > 0) {
      const features = this._defaultPolygons.map((coords, index) => ({
        type: 'Feature',
        geometry: {
          type: 'Polygon',
          coordinates: [coords]
        },
        properties: {
          height: this._defaultHeights[index] || 0
        }
      }))
      this._draw.set({
        type: 'FeatureCollection',
        features
      })
      this._restrictflyHeights = [...this._defaultHeights]
    }

    // 监听绘制完成
    map.on('draw.create', this._handleDraw.bind(this))

    return this._container
  }

  onRemove () {
    if (this._map && this._draw) {
      this._map.removeControl(this._draw)
    }
    if (this._container?.parentNode) {
      this._container.parentNode.removeChild(this._container)
    }
    this._map = null
  }

  _enableDraw () {
    if (this._draw && this._map) {
      this._draw.changeMode('draw_polygon')
    }
  }

  async _handleDraw (e) {
    const features = this._draw.getAll()
    if (features.features.length > 0) {
      const newFeature = features.features[features.features.length - 1]

      try {
        const height = await this._promptHeightInput()
        this._restrictflyHeights.push(parseFloat(height))
        // 可选：在 feature 上记录高度
        newFeature.properties.height = height
      } catch (error) {
        // 用户取消输入，移除刚才的图形
        this._draw.delete(newFeature.id)
        Message.info('已取消限飞区域绘制')
      }
    }
  }

  _deleteSelected () {
    if (this._draw) {
      const selected = this._draw.getSelectedIds()
      if (selected.length > 0) {
        // 同时删除对应的限高值（只支持最后一个被删）
        this._restrictflyHeights.pop()
        this._draw.delete(selected)
      }
    }
  }

  async _savePolygons () {
    if (!this._draw) return

    const allFeatures = this._draw.getAll()

    const polygons = allFeatures.features
      .filter(f => f.geometry.type === 'Polygon')
      .map(f => f.geometry.coordinates[0])

    try {
      await setRestrictflyData(this._shopId, polygons, this._restrictflyHeights)
      this._onSave({ polygons, heights: this._restrictflyHeights })
    } catch (error) {
      Message.error('保存限飞区失败')
      console.error(error)
    }
  }

  // Element UI 弹窗输入限高
  _promptHeightInput () {
    return MessageBox.prompt('请输入该区域的限飞高度（单位：米）', '限高设置', {
      confirmButtonText: '确定',
      cancelButtonText: '取消',
      inputPattern: /^\d+(\.\d+)?$/,
      inputErrorMessage: '请输入有效的数字'
    }).then(({ value }) => value)
  }
}

// 显示禁飞区 限飞区
export class PolygonToggleControl {
  constructor (options = {}) {
    this._map = null
    this._container = null
    this._active = false

    this.defaultIconClass = options.defaultIconClass
    this.activeIconClass = options.activeIconClass

    // 外部传入的切换回调
    this.onToggle = options.onToggle || (() => {})
  }

  onAdd (map) {
    this._map = map
    this._container = document.createElement('div')
    this._container.className = 'mapboxgl-ctrl mapboxgl-ctrl-group'

    this._button = document.createElement('button')
    this._button.type = 'button'
    this._button.className = this.defaultIconClass
    this._container.appendChild(this._button)

    this._button.addEventListener('click', () => {
      this._active = !this._active
      this._update()
      this.onToggle(this._active) // 通知外部状态切换
    })

    return this._container
  }

  onRemove () {
    this._container.parentNode.removeChild(this._container)
    this._map = null
  }

  _update () {
    if (this._active) {
      this._button.className = this.activeIconClass
    } else {
      this._button.className = this.defaultIconClass
    }
  }
}

// 保存数据到文件控件
export class SaveToFileControl {
  constructor (options = {}) {
    // 获取数据的方法，必须是一个函数，返回要保存的数据数组
    this.getData = options.Data || (() => [])

    // 保存时的默认文件名，可以通过传参自定义
    this.filename = options.filename || `data_${Date.now()}.json`

    // 按钮悬停时显示的提示文本
    this.title = options.title || '保存数据'

    // 按钮图标，可以是 emoji 或 HTML 字符
    this.icon = options.icon || '💾'
  }

  // Mapbox 会调用该方法，将控件添加到地图上
  onAdd (map) {
    this._map = map

    // 创建控件容器 div
    this._container = document.createElement('div')
    this._container.className = 'mapboxgl-ctrl mapboxgl-ctrl-group'

    // 创建按钮元素
    const button = document.createElement('button')
    button.className = 'mapboxgl-ctrl-icon'
    button.type = 'button'
    button.innerHTML = this.icon // 设置图标
    button.title = this.title // 设置悬浮提示
    button.onclick = () => this._saveToFile() // 点击事件处理：执行保存

    // 将按钮添加到控件容器中
    this._container.appendChild(button)

    // 返回控件 DOM 元素，Mapbox 会将其插入地图
    return this._container
  }

  // 保存数据为 JSON 文件的核心方法
  _saveToFile () {
    const data = this.getData() // 调用传入的 getData 方法获取数据

    // 若数据为空，则提示并返回
    if (!data || data.length === 0) {
      alert('数据为空')
      return
    }

    // 将数据序列化为 JSON 字符串（格式化缩进）
    const content = JSON.stringify(data, null, 2)

    // 创建一个 Blob 对象，用于生成文件下载链接
    const blob = new Blob([content], { type: 'application/json' })

    // 创建一个临时链接元素用于触发浏览器下载
    const link = document.createElement('a')
    link.href = URL.createObjectURL(blob) // 生成临时 URL
    link.download = this.filename // 设置下载文件名
    link.click() // 触发下载
    URL.revokeObjectURL(link.href) // 释放临时 URL
  }

  // Mapbox 会调用该方法移除控件
  onRemove () {
    // 从地图中移除 DOM 元素
    this._container.parentNode.removeChild(this._container)

    // 清除对 map 实例的引用，防止内存泄漏
    this._map = null
  }
}
