import BDMapAdapter from '../js/BDMapAdapter'
import EsriMapAdapter from '../js/EsriMapAdapter'
import GDMapAdapter from '../js/GDMapAdapter'
import { mapType } from '../js/MapLocalConfig'
import { MapLineStyle } from './BasicClass'

/**
 * @class MapAdapter
 * @classdesc 地图接口适配器(百度，高德，esri)
 * 约定：
 * 1、默认数据输入、输出坐标系为wgs84
 * 2、图层名作为图层唯一标识
 * 3、要素名作为要素唯一标识（要素包括点、线、面、信息窗、文字标注、动效）
 */
export class MapAdapter {
  /**
   * 构造函数
   * @param {string} div 地图容器dom id
   */
  constructor(div) {
    switch (window.mapconfig.mapType) {
      case mapType.Gaode:
        this.mapInstance = new GDMapAdapter(div)
        break
      case mapType.BD:
        this.mapInstance = new BDMapAdapter(div)
        break
      case mapType.Esri:
        this.mapInstance = new EsriMapAdapter(div)
        break
    }
  }

  /**
   * 加载地图实例
   * @param {Event} callback 加载地图实例回调函数
   */
  loading(callback) {
    this.mapInstance.initialMap(function (map) {
      callback(map)
    })
  }
  /**
   * 地图居中于坐标点
   * @param {number[]} center 中心点坐标 [117.204348, 39.345704]
   */
  centerAt(center) {
    this.mapInstance.centerAt(center)
  }
  /**
   * 地图缩放至指定级别并以指定点为地图显示中心点
   * @param {number[]} center 中心点坐标 [117.204348, 39.345704]
   * @param {number} zoom 缩放等级 8
   */
  setCenterAndZoom(center, zoom) {
    this.mapInstance.setCenterAndZoom(center, zoom)
  }
  /**
 * 添加点图层
 * @param {string} layername 图层名
 * @param {MapPoint[]} geoObj 构成图层的几何集合 
 * [{name: '1',
    attribute: [{name: '属性1', value: '1'}, {name: '属性2', value: 2}],
    longitude: 121.34424480994065,
    latitude: 31.20275070554727,
    style: new MapPointStyle(32, 32, require('../assets/access.png'), 0, 0, 0)},
    ...]
 */
  addPointsLayer(layername, geoObj) {
    this.mapInstance.addPointsLayer(layername, geoObj)
  }
  /**
   * 添加带文字点图层
   * @param {string} layername
   * @param {MapPointText[]} geoObj
   */
  addPointsLayerWithTxt(layername, geoObj) {
    this.mapInstance.addPointsLayerWithTxt(layername, geoObj)
  }
  /**
  * 添加线图层
  * @param {string} layername 图层名
  * @param {MapPolyline[]} geoObj 构成图层的几何集合 
  * [{name: '1',
      attribute: [{name: '线1', value: 'www'}],
      path: [[121.33531673958518, 31.170525036013],
              [121.33707307670134, 31.168245947446692],
              [121.33895720752865, 31.16563683285549],
              [121.34032748201756, 31.163101655567758],
              [121.34276918923383, 31.16452854203405]],
      style: new MapLineStyle('', 3, 0.8, MapLineType.Solid)
    },...]
  */
  addLinesLayer(layername, geoObj) {
    this.mapInstance.addLinesLayer(layername, geoObj)
  }
  /**
 * 添加面图层
 * @param {string} layername 图层名
 * @param {MapPolygon[]} geoObj 构成图层的几何集合
 * [{name: '1',
    attribute: [{name: '状态', value: '开发中'}],
    path:[[121.35827390580916, 31.170935024374813],
          [121.36026703069909, 31.16562792038188],
          [121.36875117972394, 31.167837993181326],
          [121.36750759498265, 31.170995811644683],
          [121.36705793504595, 31.17428166381015]],
    style: new MapPolygonStyle('#FF0000', '#FFFF00', 3, 1, 0.8, MapLineType.Solid) 
    },...]
 */
  addPolygonsLayer(layername, geoObj) {
    this.mapInstance.addPolygonsLayer(layername, geoObj)
  }
  /**
  * 添加文字图层
  * @param {string} layername 图层名
  * @param {MapText[]} geoObj 构成图层的几何集合 
  * [{name: '1',
      content: '属性2',
      longitude: 121.34424480994065,
      latitude: 31.20275070554727,
      style: new MapTextStyle('', 16, 'normal', [255, 0, 0], 0, -32)},
    ...]
  */
  addLabels(layername, geoObj) {
    this.mapInstance.addLabels(layername, geoObj)
  }
  /**
   * 添加信息窗口
   * @param {MapInfowindow[]} geoObj 构成图层的几何集合
   * [{name: '1',
   * content: "<div style='position:relative; width:70px; height:100px; line-height:60px; background:#D6E29A;" +
           "border-radius:4px; border:1px solid #AEBD30;><div class='cac_top'></div></div>",
     longitude: 121.33431920053995,
     latitude: 31.152811648259345,
     xOffset: 15,
     yOffset: 20},
    ...]
   */
  addInfowindow(geoObj) {
    this.mapInstance.addInfowindow(geoObj)
  }

  /**
   * 关闭指定名称信息窗
   * @param {string} name 信息窗名
   */
  closeInfowindow(name) {
    this.mapInstance.closeInfowindow(name)
  }
  /**
   * 显示指定名称信息窗
   * @param {string} name 信息窗名
   */
  openInfowindow(name) {
    this.mapInstance.openInfowindow(name)
  }
  /**
   * 移除指定名称信息窗
   * @param {string} name 信息窗名
   */
  removeInfowindow(name) {
    this.mapInstance.removeInfowindow(name)
  }
  /**
   * 根据图层名清除点/线/面图层,如果不传图层名则默认清空所有图层
   * @param {string} layername 图层名layername=undefined则清空所有数据
   */
  removeLayer(layername) {
    this.mapInstance.removeLayer(layername)
  }
  /**
   * 根据图层名、要素名（唯一标识），清除要素
   * @param {string} layername 图层名
   * @param {string} name 要素名（唯一标识）
   */
  removeElementByFieldName(layername, name) {
    this.mapInstance.removeElementByFieldName(layername, name)
  }
  /**
  * 根据图层名、要素，清除要素
  * @param {string} layername 图层名
  * @param {object} element 要清除的要素 esri：传入graphic，百度:传入要素，高德：传入要素
  * @example 点击获取需要清除的要素
  * var adp = new MapAdapter('container')
  * adp.loading(async function (mapins) {
  * var indx = that.adp.getLayerIndexByName('points')
  * adp.mapInstance.mapLayers[indx].on('click', function (e) {
          that.adp.removeElement('', e.target) //百度、高德
          //that.adp.removeElement('points', e.graphic) //esri
      })
  * }) 
  */
  removeElement(layername, element) {
    this.mapInstance.removeElement(layername, element)
  }
  /**
   * 根据图层名获得图层
   * @param {string} layername 图层名
   * @returns 图层数据
   * esri：graphicslayer
   * 高德：OverlayGroup
   * 百度：数组，各类型要素集合
   */
  getLayerByName(layername) {
    return this.mapInstance.getLyrByName(layername)
  }
  /**
   * 根据图层名获得图层坐标数据
   * @param {string} layername 图层名
   * @returns {object} { layer: layername, postion: [{lng,lat},...] }
   */
  getLayerGeometryByName(layername) {
    return this.mapInstance.getLayerGeometryByName(layername)
  }
  /**
   * 根据图层名获得图层索引
   * @param {string} layername 图层名
   * @returns 图层索引
   */
  getLayerIndexByName(layername) {
    return this.mapInstance.getLyrIndexByName(layername)
  }
  /**
   * 插入要素到某一图层
   * @param {string} layername 要插入要素的图层名
   * @param {object[]} geoObj 构成图层的几何集合 (MapPolygon|MapPolyline|MapPoint|MapText)
   *  @param {string} layertype 要插入要素的图层类型
   */
  insertintoLayer(layername, geoObj, lyrtype) {
    this.mapInstance.insertintoLayer(layername, geoObj, lyrtype)
  }
  /**
   * 添加自定义动画到指定位置
   * @param {MapAnimation[]} geoObj 构成图层的几何集合
   * [{name: '1',
      longitude: 121.56175749854266,
      latitude: 31.10738118245031,
      content: `<div class="css_animation"></div>`,
      // content: require('../assets/wave.gif'),
      xOffset: -10,
      yOffset: -10
      }]
   */
  startAnimation(geoObj) {
    this.mapInstance.startAnimation(geoObj)
  }
  /**
   * 根据动画名称移除动画
   * @param {string} name 动画名
   */
  removeAnimation(name) {
    this.mapInstance.removeAnimation(name)
  }
  /**
   * 开始覆盖物移动
   * @param {object} options 覆盖物移动参数
   * @param {string} options.name 覆盖物名称
   * @param {number[][]} options.path 移动路径
   * @param {number} options.duaration 每段动画持续时长,单位：s
   * @param {number} options.speed 每段动画速度，米/秒
   * @param {MapPointStyle} options.objectStyle 覆盖物样式
   */
  startObjectMoving(options) {
    this.mapInstance.startObjectMoving(
      options.name,
      options.path,
      options.duaration,
      options.speed,
      options.objectStyle
    )
  }
  /**
   * 暂停覆盖物移动
   */
  pauseObjectMoving(name) {
    this.mapInstance.pauseObjectMoving(name)
  }
  /**
   * 继续覆盖物移动
   */
  continueObjectMoving(name) {
    this.mapInstance.continueObjectMoving(name)
  }
  /**
   * 停止覆盖物移动
   */
  stopObjectMoving(name) {
    this.mapInstance.stopObjectMoving(name)
  }
  removeObjectMoving(name) {
    this.mapInstance.removeObjectMoving(name)
  }
  /**
   * 在地图上显示指定图层名图层
   * @param {string} layername
   */
  showLayer(layername) {
    this.mapInstance.showLayer(layername)
  }
  /**
   * 在地图上隐藏指定图层名图层
   * @param {string} layername
   */
  hideLayer(layername) {
    this.mapInstance.hideLayer(layername)
  }
  /**
   * 添加掩膜
   * @param {number[]} boundries 掩膜边界坐标数组
   * @param {MapLineStyle} borderStyle 掩膜边界线样式
   */
  setLayerMask(boundries, borderStyle) {
    this.mapInstance.setLayerMask(boundries, borderStyle)
  }
  /**
   * 移除掩膜
   */
  removeLayerMask() {
    this.mapInstance.removeLayerMask()
  }
  /**
   * 根据关键字搜索poi
   * @param {string} keyword
   */
  searchByKeyword(keyword) {
    this.mapInstance.searchByKeyword(keyword)
  }
  /**
   * 销毁地图实例
   */
  destroyMap() {
    this.mapInstance.destroyMap()
  }
  /**
   * 获取地图实例
   * @returns 地图实例
   */
  getMap() {
    return this.mapInstance.map
  }
  /**
   * 获取地图中心点
   * @returns 地图中心点坐标 [lng,lat]
   */
  getCenter() {
    return this.mapInstance.getCenter()
  }
  /**
   * 获取地图缩放级别
   * @returns 地图缩放级别
   */
  getZoom() {
    return this.mapInstance.map.getZoom()
  }
  /**
   * 获取地图最小缩放级别
   * @returns 地图最小缩放级别
   */
  getMinZoom() {
    return this.mapInstance.getMinZoom()
  }
  /**
   * 获取地图最大缩放级别
   * @returns 地图最大缩放级别
   */
  getMaxZoom() {
    return this.mapInstance.getMaxZoom()
  }
  /**
   *注册事件
   * @param {string} eventType mouseover,mouseout,click,
   * @param {function} callback
   */
  on(eventType, callback) {
    this.mapInstance.addEventListener(eventType, function (e) {
      callback(e)
    })
  }
  /**
   * 移除事件
   * @param {string} eventType mouseover,mouseout,click,
   */
  off(eventType) {
    this.mapInstance.removeEventListener(eventType)
  }
  /**
   * 新建指定图层类型要素
   * @param {MapLayerType} layerType 图层类型：
   * 包括：line 线图层
   * point 点图层
   * polygon 面图层
   */
  startEditing(layerType) {
    this.mapInstance.mapEditor.startEditing(layerType)
  }
  /**
   * 停止新建要素
   */
  stopEditing() {
    this.mapInstance.mapEditor.stopEditing()
  }
  /**
   * 保存新建要素到指定图层名图层中
   * @param {string} layername 图层名
   * @returns {object} { layer: layername, postion: [{lng,lat},...] }
   */
  saveEditing(layername) {
    return this.mapInstance.mapEditor.saveEditing(layername)
  }
  /**
   * 编辑指定图层
   * @param {string} layername 图层名
   */
  enableLayerEditing(layername) {
    this.mapInstance.enableLayerEditing(layername)
  }
  /**
   * 停止编辑指定图层
   * @param {string} layername
   */
  disableLayerEditing(layername) {
    this.mapInstance.disableLayerEditing(layername)
  }
}
