import { message } from 'ant-design-vue'
/**
 * 地图适配器抽象基类
 *
 * 设计模式：适配器模式（Adapter Pattern）
 *
 * 作用：
 * 1. 定义统一的地图操作接口，屏蔽不同地图内核（高德、OpenLayers）的实现差异
 * 2. 业务层通过统一接口调用地图功能，无需关心底层使用的是哪个地图引擎
 * 3. 便于扩展新的地图内核，只需实现此接口即可
 *
 * 使用方式：
 * - 子类必须实现所有抽象方法
 * - 所有方法返回 Promise，支持异步操作和链式调用
 *
 * @class MapAdapter
 */
export default class MapAdapter {
  /**
   * 初始化地图实例
   *
   * @param {string|HTMLElement} container - 地图容器 DOM 元素或选择器字符串
   * @param {object} options - 地图初始化配置项
   * @param {Array<number>} options.center - 地图中心点坐标 [经度, 纬度]
   * @param {number} options.zoom - 初始缩放级别
   * @param {Array<number>} options.zooms - 缩放范围 [最小级别, 最大级别]
   * @param {number} options.defaultMaxZoom - 默认底图最大缩放级别
   * @param {number} options.satelliteMaxZoom - 卫星底图最大缩放级别
   * @returns {Promise} 返回地图实例的 Promise
   * @abstract
   */
  initMap (container, options = {}) {
    throw new Error('initMap must be implemented by subclass')
  }

  /**
   * 批量添加标记点（Marker）
   *
   * @param {Function} getDataFn 获取标记点数据的函数，返回 Promise<Array<object>>
   *  返回的数据格式：[{ id, name, lng, lat, icon? }]
   * @param {object} options 组配置选项
   * @param {string} options.groupId 组数据唯一标识（必填）
   * @param {string} options.groupName 组数据名称（必填）
   * @param {boolean} [options.visible=true] 默认是否显示，默认 true
   * @param {boolean} [options.isAutoRefresh=false] 是否定时刷新，默认 false
   * @param {number} [options.refreshInterval=10] 定时间隔（秒），默认 10 秒
   * @param {boolean} [options.showLabel=false] 是否显示文本标签，默认 false
   * @param {string} [options.labelPosition='bottom'] 标签位置，默认 'bottom'，可选值：'top'|'right'|'bottom'|'left'|'center'
   * @param {Function} [onClick] 可选，点位点击回调 (payload) => void
   *  回调入参约定：{ id, name, coordinate: [lng, lat], event?, marker?/feature? }
   * @returns {Promise<Array>} 返回标记点实例数组的 Promise
   * @abstract
   */
  addMarker (getDataFn, options = {}, onClick) { // eslint-disable-line no-unused-vars
    throw new Error('addMarker must be implemented by subclass')
  }

  /**
   * 添加热力图
   *
   * @param {Function} getDataFn 获取热力图数据的函数，返回 Promise<Array<object>>
   *  返回的数据格式：[{ lng, lat, count }]
   * @param {object} options 组配置选项
   * @param {string} options.groupId 组数据唯一标识（必填）
   * @param {string} options.groupName 组数据名称（必填）
   * @param {boolean} [options.visible=true] 默认是否显示，默认 true
   * @returns {Promise} 返回热力图实例的 Promise
   * @abstract
   */
  addHeatmap (getDataFn, options = {}) { // eslint-disable-line no-unused-vars
    throw new Error('addHeatmap must be implemented by subclass')
  }

  /**
   * 批量绘制多边形
   *
   * @param {Function} getDataFn - 获取多边形数据的函数，返回 Promise<Array<object>>
   *  返回的数据格式：[
   *    { id: string, name: string, points: Array<Array<number>>, strokeColor?: string, fillColor?: string, strokeWidth?: number }
   *  ]
   * @param {object} options - 组配置选项
   * @param {string} options.groupId - 组数据唯一标识（必填）
   * @param {string} options.groupName - 组数据名称（必填）
   * @param {boolean} [options.visible=true] - 默认是否显示，默认 true
   * @returns {Promise<Array>} 返回多边形实例数组的 Promise
   * @abstract
   */
  drawPolygon (getDataFn, options = {}) {
    throw new Error('drawPolygon must be implemented by subclass')
  }

  /**
   * 添加单个 WMS 图层
   *
   * @param {object} layerOptions - WMS 图层配置对象
   * @param {string} layerOptions.id - 图层唯一标识（必填）
   * @param {string} layerOptions.name - 图层名称（必填）
   * @param {string} layerOptions.url - WMS 服务地址
   * @param {object} layerOptions.params - WMS 请求参数，如 { LAYERS: 'layer_name' }
   * @param {boolean} [layerOptions.visible=true] - 初始显隐
   * @param {Function} [layerOptions.getLayerVersion] - 可选：外部传入的版本号获取函数
   *  约定签名：(tableName: string) => (Promise<number|string>|number|string)
   * @param {string} groupId - 组数据唯一标识（必填）
   * @param {string} groupName - 组数据名称（必填）
   * @param {string} [groupType='wms'] - 组类型标识
   * @returns {Promise<Array>} 返回图层实例数组的 Promise（单元素）
   * @abstract
   */
  addWmsLayer (layerOptions, groupId, groupName, groupType = 'wms') { // eslint-disable-line no-unused-vars
    throw new Error('addWmsLayer must be implemented by subclass')
  }

  /**
   * 批量绘制折线
   *
   * @param {Function} getDataFn - 获取折线数据的函数，返回 Promise<Array<object>>
   * @param {object} options - 组配置选项
   * @param {string} options.groupId - 组数据唯一标识（必填）
   * @param {string} options.groupName - 组数据名称（必填）
   * @param {boolean} [options.visible=true] - 默认是否显示
   */
  addPolyline (getDataFn, options = {}) {
    throw new Error('addPolyline must be implemented by subclass')
  }

  /**
   * 开启组闪烁（通过显隐切换）
   * @param {string} groupId 组 ID
   * @param {number} interval 闪烁间隔，默认 600ms
   */
  startGroupBlink (groupId, interval = 600) { // eslint-disable-line no-unused-vars
    throw new Error('startGroupBlink must be implemented by subclass')
  }

  /**
   * 停止组闪烁并恢复显示
   * @param {string} groupId 组 ID
   */
  stopGroupBlink (groupId) { // eslint-disable-line no-unused-vars
    throw new Error('stopGroupBlink must be implemented by subclass')
  }

  /**
   * 开启自由画线交互
   * @param {Function} onComplete 绘制完成回调 (coordinates: Array<[lng,lat]>)
   */
  startLineDraw (onComplete) { // eslint-disable-line no-unused-vars
    throw new Error('startLineDraw must be implemented by subclass')
  }

  /**
   * 停止自由画线交互
   */
  stopLineDraw () {
    throw new Error('stopLineDraw must be implemented by subclass')
  }

  /**
   * 开启单条直线绘制（目前仅用于切面分析）
   * 只能绘制一条直线（两个点），绘制完成后自动结束交互
   * @param {Function} onComplete 完成回调，参数为坐标数组 [[lng, lat], [lng, lat]]（4326坐标）
   */
  startStraightLineDraw (onComplete) { // eslint-disable-line no-unused-vars
    throw new Error('startStraightLineDraw must be implemented by subclass')
  }

  /**
   * 清理图层
   *
   * @param {string} [layerId] - 要清理的图层 ID；不传则清理所有业务图层
   * @returns {Promise} 返回清理结果的 Promise
   * @abstract
   */
  clearLayer (layerId) {
    throw new Error('clearLayer must be implemented by subclass')
  }

  /**
   * 切换底图类型
   *
   * 支持的底图类型：
   * - 'gaode' / 'gaodeVec': 高德矢量地图
   * - 'gaodeSat': 高德卫星地图 + 标注
   * - 'tdtVec': 天地图矢量地图 + 标注
   * - 'tdtImg': 天地图影像地图 + 标注
   *
   * 注意：不同地图内核支持的底图类型可能不同
   *
   * @param {string} mapType - 底图类型标识
   * @returns {Promise|void} 返回切换结果的 Promise 或 void
   * @abstract
   */
  switchBaseMap (mapType) {
    message.error('该模式未实现此功能')
  }

  /**
   * 设置组数据显隐状态
   *
   * 当设置为显示时，会重新调用数据获取函数获取最新数据并更新图层
   *
   * @param {string} groupId - 组数据唯一标识
   * @param {boolean} visible - 是否显示
   * @returns {Promise<void>}
   * @abstract
   */
  setGroupVisible (groupId, visible) {
    message.error('该模式未实现此功能')
  }

  /**
   * 获取所有组数据信息
   *
   * @returns {Promise<Array<object>>} 返回组数据信息数组，格式：[{ id, name, type, visible, count }]
   * @abstract
   */
  getGroups () {
    message.error('该模式未实现此功能')
  }

  /**
   * 获取指定组数据信息
   *
   * @param {string} groupId - 组数据唯一标识
   * @returns {Promise<object>} 获取到的组数据信息，格式：{ id, name, type, visible, count }
   * @abstract
   */
  getGroupById (groupId) {
    message.error('该模式未实现此功能')
  }

  /**
   * 根据 type 获取图层组，如果不传 type 则返回所有组
   * @param {string} [type] - 可选，要过滤的图层类型 (如 'marker', 'polygon')
   * @returns {Array<Object>} 过滤后的图层组数组
   */
  getGroupsByType (type) {
    message.error('该模式未实现此功能')
  }

  /**
   * 将图层组按 groupType 分类，或获取指定分类的图层组
   * @param {string} [specificGroupType] - 可选，指定要获取的 groupType
   * @returns {Array<Object>|Array<{groupType: string, groups: Array<Object>}>}
   *          如果传入了 specificGroupType，返回该分类的组数组；
   *          否则，返回所有分类的对象数组。
   */
  getGroupsByGroupType (specificGroupType) {
    message.error('该模式未实现此功能')
  }

  /**
   * 获取地图当前状态
   * 用于切换引擎时保存状态
   *
   * @returns {object|null} 地图状态对象，包含 center, zoom, groups 等信息
   * @abstract
   */
  getMapState () {
    message.error('该模式未实现此功能')
  }

  /**
   * 销毁地图实例
   * 用于切换引擎时清理资源
   *
   * @abstract
   */
  destroy () {
    message.error('该模式未实现此功能')
  }

  /**
   * 绑定视图变更回调（中心/缩放等）
   * @param {Function} callback - (center: [lng, lat]) => void
   */
  bindViewChange (callback) {
    message.error('该模式未实现此功能')
  }

  /**
   * 地图放大
   * @returns {void}
   * @abstract
   */
  zoomIn () {
    message.error('该模式未实现此功能')
  }

  /**
   * 地图缩小
   * @returns {void}
   * @abstract
   */
  zoomOut () {
    message.error('该模式未实现此功能')
  }

  /**
   * 设置地图视图
   * @param {number} zoom - 缩放级别
   * @param center
   * @returns {void}
   * @abstract
   */
  fitView (zoom = null, center = null) {
    message.error('该模式未实现此功能')
  }

  /**
   * 启用框选放大功能
   * @returns {void}
   * @abstract
   */
  enableZoomToBox () {
    message.error('该模式未实现此功能')
  }

  /**
   * 禁用框选放大功能
   * @returns {void}
   * @abstract
   */
  disableZoomToBox () {
    message.error('该模式未实现此功能')
  }

  /**
   * 启动距离测量
   * 需要在实现里支持多次测量、回调返回累积结果
   * @param {Function} onResultChange - (results: Array<{id, distance, color}>) => void
   */
  startDistanceMeasure (onResultChange) {
    message.error('该模式未实现此功能')
  }

  /**
   * 清空测量结果并退出测量模式
   */
  clearMeasureResults () {
    message.error('该模式未实现此功能')
  }

  /**
   * 启动面积测量
   */
  startAreaMeasure () {
    message.error('该模式未实现此功能')
  }

  /**
   * 切换地图 2D / 3D 视图
   */
  setMapViewMode () {
    message.error('该模式未实现此功能')
  }

  /**
   * 获取当前地图视图模式
   */
  getMapViewMode () {
    message.error('该模式未实现此功能')
  }

  /**
   * 启动矩形框选
   * @param {Function} onComplete - (coords: Array<[lng, lat]>) => void
   */
  startRectangleSelect (onComplete) {
    throw new Error('startRectangleSelect must be implemented by subclass')
  }

  /**
   * 启动圆形框选
   * @param {Function} onComplete - (coords: Array<[lng, lat]>) => void
   */
  startCircleSelect (onComplete) {
    throw new Error('startCircleSelect must be implemented by subclass')
  }

  /**
   * 启动多边形选择
   * @param {Function} onComplete - (coords: Array<[lng, lat]>) => void
   */
  startPolygonSelect (onComplete) {
    throw new Error('startPolygonSelect must be implemented by subclass')
  }

  /**
   * 停止当前选择交互并清理
   */
  stopSelectInteraction () {
    throw new Error('stopSelectInteraction must be implemented by subclass')
  }

  /**
   * 清空选择结果
   */
  clearSelectResults () {
    throw new Error('clearSelectResults must be implemented by subclass')
  }

  /**
   * 当前定位
   * 获取用户当前位置并定位到地图中心
   * @returns {Promise<{longitude: number, latitude: number}>} 返回定位坐标 [经度, 纬度]
   * @abstract
   */
  locateCurrent () {
    throw new Error('locateCurrent must be implemented by subclass')
  }

  /**
   * 设置地图点击回调
   * @param {Function} callback - 回调函数 (coordinate: [lng, lat]) => void
   */
  setMapClickCallback (callback) { // eslint-disable-line no-unused-vars
    throw new Error('setMapClickCallback must be implemented by subclass')
  }

  /**
   * 设置地图点击启用状态
   * @param {boolean} enabled
   */
  setMapClickEnabled (enabled) { // eslint-disable-line no-unused-vars
    throw new Error('setMapClickEnabled must be implemented by subclass')
  }

  /**
   * 刷新当前显示的WMS图层（强制刷新缓存）
   * 只更新时间戳参数，不移除图层
   * key: 刷新指定图层
   */
  refreshWmsLayers (key) {
    throw new Error('refreshWmsLayers must be implemented by subclass')
  }

  /**
   * 打开信息窗口
   * @param {Array<number>} coordinate - 坐标 [lng, lat]
   * @param {HTMLElement} content - 窗口内容（DOM元素）
   *  注意：Vue 组件在调用层（如 index.vue）中已挂载为 DOM 元素，适配器只接收 DOM 元素
   * @param {object} [options] - 可选配置
   * @param {number} [options.width] - 窗口宽度（像素）
   * @param {number} [options.height] - 窗口高度（像素）
   * @param {boolean} [options.closeOnClick] - 点击地图是否关闭窗口
   * @returns {Promise<void>}
   * @abstract
   */
  openInfoWindow (coordinate, content, options = {}) {
    throw new Error('openInfoWindow must be implemented by subclass')
  }

  /**
   * 关闭信息窗口
   * @returns {Promise<void>}
   * @abstract
   */
  closeInfoWindow () {
    throw new Error('closeInfoWindow must be implemented by subclass')
  }

  /**
   * 添加轨迹
   * 只添加轨迹数据，不播放
   * @param {Array<{key: string, path: Array<{x: number, y: number}>}>} segments - 轨迹段数组
   * @param {object} config - 轨迹配置
   * @param {number} [config.speed=1] - 播放速度倍数，范围 0.1～100，默认 1
   * @param {number} [config.baseSpeed=1] - 基础速度，单位 m/s，默认 1
   * @param {string} [config.unplayedColor='#ff0000'] - 未播放轨迹颜色，默认红色
   * @param {string} [config.playedColor='#00ff00'] - 已播放轨迹颜色，默认绿色
   * @param {string} [config.startIcon] - 起点图标路径
   * @param {string} [config.endIcon] - 终点图标路径
   * @param {string} [config.carIcon] - 播放中小车图标路径
   * @returns {Promise<void>}
   * @abstract
   */
  addTrajectory (segments, config = {}) {
    throw new Error('addTrajectory must be implemented by subclass')
  }

  /**
   * 开始播放轨迹
   * 从当前段、当前进度开始播放。没有进度调用重新播放，有进度调用继续播放
   * @returns {Promise<void>}
   * @abstract
   */
  startTrajectory () {
    throw new Error('startTrajectory must be implemented by subclass')
  }

  /**
   * 重新播放轨迹
   * 从第一段、起点重新播放
   * @returns {Promise<void>}
   * @abstract
   */
  replayTrajectory () {
    throw new Error('replayTrajectory must be implemented by subclass')
  }

  /**
   * 暂停播放轨迹
   * @returns {Promise<void>}
   * @abstract
   */
  pauseTrajectory () {
    throw new Error('pauseTrajectory must be implemented by subclass')
  }

  /**
   * 继续播放轨迹
   * 从当前段、当前进度开始播放
   * @returns {Promise<void>}
   * @abstract
   */
  resumeTrajectory () {
    throw new Error('resumeTrajectory must be implemented by subclass')
  }

  /**
   * 清除轨迹
   * 清除所有轨迹和状态
   * @returns {Promise<void>}
   * @abstract
   */
  clearTrajectory () {
    throw new Error('clearTrajectory must be implemented by subclass')
  }

  /**
   * 获取轨迹播放状态
   * @returns {object} 轨迹状态对象
   * @property {Array<{key: string, path: Array<{x: number, y: number}>}>} segments - 原始轨迹数据
   * @property {number} currentIndex - 当前播放的轨迹段索引
   * @property {number} progress - 当前段播放进度 0～1
   * @property {number} speed - 当前播放速度倍数
   * @property {object} config - 实际使用的轨迹配置
   * @property {string} status - 当前播放状态: 'idle' | 'playing' | 'paused' | 'finished'
   * @abstract
   */
  getTrajectoryState () {
    throw new Error('getTrajectoryState must be implemented by subclass')
  }

  /**
   * 设置轨迹播放状态
   * @param {object|string} stateOrKey - 完整状态对象或字段名
   * @param {*} value - 字段值（当第一个参数为字段名时）
   * @returns {Promise<void>|void}
   * @abstract
   */
  setTrajectoryState (stateOrKey, value) { // eslint-disable-line no-unused-vars
    throw new Error('setTrajectoryState must be implemented by subclass')
  }
}
