类名 common/document/mapCollection/Map.js
import { Zondy, Evented, Collection, LayerEvent } from '../../base'
import { LayerType, MapEventType } from '../../base/enum'
import { Layer, SubLayer } from '../layer/baseLayer'
import { cloneObject, defaultValue, isNull, toJSON } from '../../util'
import {
  IGSMapImageLayer,
  WMSLayer,
  IGSTileLayer,
  WMTSLayer,
  IGSFeatureLayer,
  GeoJSONLayer,
  WFSLayer,
  GraphicsLayer,
  IGSVectorTileLayer,
  M3DModelCacheLayer,
  Cesium3DTilesCacheLayer,
  IGSSceneLayer,
  TerrainCacheLayer
} from '../layer'

/**
 * 图层管理容器,和地图引擎无关,通过此对象而不是地图引擎来对图层进行管理
 * <br>[ES5引入方式]:<br/>
 * Zondy.Map() <br/>
 * [ES6引入方式]:<br/>
 * import { Map } from "@mapgis/webclient-common" <br/>
 * @class Map
 * @moduleEX MapModule
 * @extends Evented
 * @fires Map#添加图层事件
 * @fires Map#添加多个图层事件
 * @fires Map#删除图层事件
 * @fires Map#移除多个图层事件
 * @fires Map#移除所有图层事件
 * @param {Object} options 构造参数
 * @param {Basemap}  [options.basemap] 设置地图视图中的底图;<br/>
 * 1、如果底图存在,则会使用底图上的参考系作为地图视图的参考系,如果没有,则使用常规图层上的坐标系;<br/>
 * 2、底图图层在常规图层的最下面;
 * 3、除GraphicsLayer外的二维地图都可以作为底图<br/>
 *
 * @summary <h5>支持如下方法:</h5>
 * <a href='#add'>[1、添加图层对象]</a><br/>
 * <a href='#addMany'>[2、添加多个图层]</a><br/>
 * <a href='#findLayerById'>[3、根据id查询图层]</a><br/>
 * <a href='#remove'>[4、删除指定图层]</a><br/>
 * <a href='#removeMany'>[5、移除多个图层]</a><br/>
 * <a href='#removeAll'>[6、删除所有图层]</a><br/>
 * <a href='#reorder'>[7、调整图层顺序]</a><br/>
 * <a href='#destroy'>[8、销毁Map对象]</a><br/>
 * <a href='#fromJSON'>[9、通过json对象构造并返回一个新的Map对象]</a><br/>
 * <a href='#toJSON'>[10、转换为json对象]</a><br/>
 * <a href='#clone'>[11、克隆并返回一个新的Map对象]</a><br/>
 *
 * @example <caption><h7 id='valueExpression'>初始化Map对象</h7></caption>
 * // ES5引入方式
 * const { Map } = Zondy
 * // ES6引入方式
 * import { Map } from "@mapgis/webclient-common"
 * //创建Map对象
 * let map = new Map();
 *
 * @example <caption><h7 id='valueExpression'>添加底图图层</h7></caption>
 * // ES5引入方式
 * const { Map, Basemap, Collection } = Zondy
 * const { IGSTileLayer } = Zondy.Layer
 * // ES6引入方式
 * import { Map, Basemap, Collection, IGSTileLayer } from "@mapgis/webclient-common"
 * //创建Map对象
 * const map = new Map({
 *   // 初始化底图图层集合
 *   basemap: new Basemap({
 *     // 可以设置多个图层到底图集合中
 *     baseLayers: new Collection(
 *       [
 *         // 创建一个图层
 *         new IGSTileLayer({
 *           url: '服务及地址'
 *         })
 *       ]
 *     )
 *   })
 * });
 */

/**
 * 添加图层事件
 * @event Map#添加图层事件
 * @property {Object} event 事件对象
 * @property {String} [event.type = 'layer-add'] 添加图层事件
 * @property {Layer} [event.layer = null] 被添加的图层对象
 * @property {View} [event.view = null] 地图视图对象
 * @property {Map} [event.sourceTarget = null] 事件发起对象
 * @property {View} [event.target = null] 事件接收对象
 * @example <caption><h5>添加图层事件</h5></caption>
 * map.on('layer-add', function (event) {
 *   // 添加图层事件
 *   console.log("添加图层事件:", event)
 * });
 */

/**
 * 添加多个图层事件
 * @event Map#添加多个图层事件
 * @property {Object} event 事件对象
 * @property {String} [event.type = 'layer-add-many'] 添加多个图层事件
 * @property {Array<Layer>} [event.layers = []] 被添加的所有图层对象数组
 * @property {View} [event.view = null] 地图视图对象
 * @property {Map} [event.sourceTarget = null] 事件发起对象
 * @property {View} [event.target = null] 事件接收对象
 * @example <caption><h5>添加多个图层事件</h5></caption>
 * map.on('layer-add-many', function (event) {
 *   // 添加多个图层事件
 *   console.log("添加图层事件:", event)
 * });
 */

/**
 * 删除图层事件
 * @event Map#删除图层事件
 * @property {Object} event 事件对象
 * @property {String} [event.type = 'layer-remove'] 删除图层事件
 * @property {Layer} [event.layer = null] 被删除的图层对象
 * @property {View} [event.view = null] 地图视图对象
 * @property {Map} [event.sourceTarget = null] 事件发起对象
 * @property {View} [event.target = null] 事件接收对象
 * @example <caption><h5>删除图层事件</h5></caption>
 * map.on('layer-remove', function (event) {
 *   // 删除图层事件
 *   console.log("删除图层事件:", event)
 * });
 */

/**
 * 移除多个图层事件
 * @event Map#移除多个图层事件
 * @property {Object} event 事件对象
 * @property {String} [event.type = 'layer-remove-many'] 移除多个图层事件
 * @property {Array<Layer>} [event.layers = []] 被删除的所有图层对象数组
 * @property {View} [event.view = null] 地图视图对象
 * @property {Map} [event.sourceTarget = null] 事件发起对象
 * @property {View} [event.target = null] 事件接收对象
 * @example <caption><h5>移除多个图层事件</h5></caption>
 * map.on('layer-remove-many', function (event) {
 *   // 移除多个图层事件
 *   console.log("移除多个图层事件:", event)
 * });
 */

/**
 * 移除所有图层事件
 * @event Map#移除所有图层事件
 * @property {Object} event 事件对象
 * @property {String} [event.type = 'layer-remove-all'] 移除所有图层事件
 * @property {View} [event.view = null] 地图视图对象
 * @property {Map} [event.sourceTarget = null] 事件发起对象
 * @property {View} [event.target = null] 事件接收对象
 * @example <caption><h5>移除所有图层事件</h5></caption>
 * map.on('layer-remove-all', function (event) {
 *   // 移除所有图层事件
 *   console.log("移除所有图层事件:", event)
 * });
 */
class Map extends Evented {
  constructor(options) {
    options = defaultValue(options, {})
    super()
    /**
     * 图层管理容器中包含的子图层
     * @member {Collection} Map.prototype.layers
     */
    this.layers = new Collection()
    /**
     * 图层管理容器中所有的子图层,包括子图层的子图层,并穷举所有子图层
     * @member {Collection} Map.prototype.allLayers
     */
    this.allLayers = new Collection()
    /**
     * 基础地图
     * @member {Collection} Map.prototype.basemap
     */
    this._basemap = defaultValue(options.basemap, undefined)
    // 是否绑定Cesium
    this._initCesiumView = false
    // 是否绑定Leaflet
    this._initLeafletView = false
    // 是否删除全部图层
    this._isRemoveAll = false
    // 是否删除多个图层
    this._isRemoveMany = false
  }

  /**
   * 通过json对象构造并返回一个新的Map对象<a id='fromJSON'></a>
   * @param {Object} json json数据
   * @return {Map} 一个新的Map对象
   * */
  static fromJSON(json) {
    json = defaultValue(json, {})
    const layers = defaultValue(json.layers, [])

    const map = new Map()
    for (let i = 0; i < layers.length; i++) {
      let _layer
      switch (layers[i].type) {
        case LayerType.igsMapImage:
          _layer = IGSMapImageLayer.fromJSON(layers[i])
          break
        case LayerType.igsTile:
          _layer = IGSTileLayer.fromJSON(layers[i])
          break
        case LayerType.wms:
          _layer = WMSLayer.fromJSON(layers[i])
          break
        case LayerType.wmts:
          _layer = WMTSLayer.fromJSON(layers[i])
          break
        case LayerType.igsFeature:
          _layer = IGSFeatureLayer.fromJSON(layers[i])
          break
        case LayerType.geojson:
          _layer = GeoJSONLayer.fromJSON(layers[i])
          break
        case LayerType.wfs:
          _layer = WFSLayer.fromJSON(layers[i])
          break
        case LayerType.graphics:
          _layer = GraphicsLayer.fromJSON(layers[i])
          break
        case LayerType.igsVectorTile:
          _layer = IGSVectorTileLayer.fromJSON(layers[i])
          break
        case LayerType.m3dCache:
          _layer = M3DModelCacheLayer.fromJSON(layers[i])
          break
        case LayerType.cesium3DTiles:
          _layer = Cesium3DTilesCacheLayer.fromJSON(layers[i])
          break
        case LayerType.scene:
          _layer = IGSSceneLayer.fromJSON(layers[i])
          break
        case LayerType.terrain:
          _layer = TerrainCacheLayer.fromJSON(layers[i])
          break
        default:
          break
      }
      map.add(_layer)
    }

    return map
  }

  /**
   * 转换为json对象<a id='toJSON'></a>
   * @return {Object} 导出的json对象
   */
  toJSON() {
    const _json = {}
    _json.layers = []
    for (let i = 0; i < this.layers.items.length; i++) {
      _json.layers.push(toJSON(this.layers.items[i], Layer))
    }

    // 设置导出配置
    // 导出时间
    _json['exportTime'] = new Date().toISOString()

    return _json
  }

  /**
   * 克隆并返回一个新的Map对象<a id='clone'></a>
   * @return {Map} 一个新的Map对象
   */
  clone() {
    return cloneObject(this)
  }

  /**
   * 添加图层对象<a id='add'></a>
   * @param {Object} layer 要添加的图层对象
   * @example
   * //添加图层
   * map.add(layer);
   */
  add(layer) {
    if (layer) {
      // layer = Layer.fromJSON(layer.toJSON())
      if (this.findLayerById(layer.id)) {
        throw new Error(`id为'${layer.id}'的图层重复添加,请检查传入图层的id`)
      }
      if (!layer._isBasemapLayer) {
        this._setLayerIndex(layer)
      } else {
        this._setBasemapIndex(layer)
      }
      layer.setMap(this)
      this.layers.add(layer)
      this.dispatchEvent(MapEventType.layerAdd, {
        type: MapEventType.layerAdd,
        target: this,
        layer
      })
    }
  }

  // 设置basemap图层顺序
  _setBasemapIndex(baseLayer) {
    let maxBaseLayerIndex = null
    let minLayerIndex = null
    if (isNull(baseLayer.index)) {
      this.layers.forEach((layer) => {
        if (
          layer._isBasemapLayer &&
          (minLayerIndex === null || maxBaseLayerIndex < layer.index)
        ) {
          maxBaseLayerIndex = layer.index
        } else if (
          !layer._isBasemapLayer &&
          (minLayerIndex === null || minLayerIndex > layer.index)
        ) {
          minLayerIndex = layer.index
        }
      })
    }
    if (minLayerIndex !== null && baseLayer.index >= minLayerIndex) {
      throw new Error(`id为'${baseLayer.id}'的基础图层index不合法`)
    }
    if (minLayerIndex === null) {
      this._setLayerIndex(baseLayer)
    } else {
      if (maxBaseLayerIndex === null) {
        baseLayer.index = 0
      } else if (maxBaseLayerIndex < minLayerIndex) {
        baseLayer.index = maxBaseLayerIndex + 1
      } else {
        baseLayer.index = minLayerIndex
      }
      this.layers.forEach((layer) => {
        if (!layer._isBasemapLayer) {
          layer.index++
        }
      })
    }
  }

  _getSRLayer() {
    const layers = this.layers.all()
    let layer = undefined

    for (let i = 0; i < layers.length; i++) {
      if (layers[i]._isSRLayer) {
        layer = layers[i]
        break
      }
    }

    return layer
  }

  /**
   * 销毁Map对象<a id='destroy'></a>
   * @example
   * map.destroy()
   */
  destroy() {
    const layers = this.layers.all()
    for (let i = 0; i < layers.length; i++) {
      this.remove(layers[i])
    }
    this.layers = undefined
  }

  /**
   * 根据id查询图层<a id='findLayerById'></a>
   * @param {String} id 图层id
   * @return Object 找到的图层
   * @example
   * //根据id查询图层
   * map.findLayerById('图层id');
   */
  findLayerById(id) {
    const index = this.layers.findIndex((v) => v.id === id)
    if (index > -1) {
      return this.layers.get(index)
    }
    return undefined
  }

  /**
   * 删除指定图层,需要传入一个图层对象<a id='remove'></a>
   * @param {Object} layer 要删除的图层对象
   * @example
   * //删除指定图层
   * map.findLayerById(layer);
   */
  remove(layer) {
    // 如果是basemap上的baseLayer,则不受删除map上图层影响
    if (layer && layer._isBasemapLayer) {
      return
    }
    if (layer) {
      // todo 删除图层时将loaded置为false
      layer.loaded = false
      // end todo
      layer.destroy()
      this.layers.remove(layer)
      // 删除allLayers中的图层
      this.allLayers.remove(layer)
      // 删除关联的子图层
      let _allLayers = [].concat(this.allLayers.items)
      for (let i = 0; i < _allLayers.length; i++) {
        if (_allLayers[i] instanceof SubLayer) {
          const _parentLayer = _allLayers[i].layer
          if (_parentLayer && _parentLayer.id && _parentLayer.id === layer.id) {
            this.allLayers.remove(_allLayers[i])
          }
        }
      }
      _allLayers = undefined
      this.dispatchEvent(MapEventType.layerRemove, {
        type: MapEventType.layerRemove,
        target: this,
        layer
      })
    }
  }

  /**
   * 删除所有图层<a id='removeAll'></a>
   * @example
   * map.removeAll();
   */
  removeAll() {
    let _items = []
    this._isRemoveAll = true
    for (let i = 0; i < this.layers.items.length; i++) {
      _items.push(this.layers.items[i])
    }
    const self = this
    _items.forEach(function (layer) {
      self.remove(layer)
    })
    _items = undefined
    this.dispatchEvent(MapEventType.layerRemoveAll, {
      type: MapEventType.layerAdd,
      target: this
    })
    this._isRemoveAll = false
  }

  /**
   * 添加多个图层<a id='addMany'></a>
   * @param {Array} layers 要添加的图层数组
   * @example
   * map.addMany(layers);
   */
  addMany(layers) {
    if (!layers) return this
    let _isAdd = false
    if (layers instanceof Layer) {
      this.add(layers)
      _isAdd = true
    } else if (Array.isArray(layers)) {
      layers.forEach((layer) => {
        if (layer instanceof Layer) {
          this.add(layer)
        }
      })
      _isAdd = true
    } else {
      arguments.forEach((layer) => {
        if (layer instanceof Layer) {
          this.add(layer)
        }
      })
      _isAdd = true
    }

    if (_isAdd) {
      this.dispatchEvent(MapEventType.layerAddMany, {
        type: MapEventType.layerAddMany,
        target: this,
        layers
      })
    }
  }

  /**
   * 移除多个图层<a id='removeMany'></a>
   * @param {Array} layers 要移除的图层数组
   * @example
   * map.removeMany(layers);
   */
  removeMany(layers) {
    if (!layers) return this
    let _isRomove = false
    this._isRemoveMany = true
    if (layers instanceof Layer) {
      this.remove(layers)
      _isRomove = true
    } else if (Array.isArray(layers)) {
      layers.forEach((layer) => {
        if (layer instanceof Layer) {
          this.remove(layer)
        }
      })
      _isRomove = true
    } else {
      arguments.forEach((layer) => {
        if (layer instanceof Layer) {
          this.remove(layer)
        }
      })
      _isRomove = true
    }
    if (_isRomove) {
      this.dispatchEvent(MapEventType.layerRemoveMany, {
        type: MapEventType.layerAddMany,
        target: this,
        layers
      })
    }
    this._isRemoveMany = false
  }

  /**
   * 调整图层顺序<a id='reorder'></a>
   * @param {Object} layer 要调整顺序的图层
   * @param {Number} index 指定的index
   * @example
   * map.reorder(layer, '要移动到的index');
   */
  reorder(layer, index) {
    this._reorder(layer, index)
  }

  _reorder(layer, index) {
    layer.index = index
    const _layerSet = this._getSmallEqualLargeLayers(layer)
    if (_layerSet.equalIndexLayer) {
      this._moveEqualLayer(layer, _layerSet.equalIndexLayer)
    }
    // 如果smallIndexLayer存在
    else if (_layerSet.smallIndexLayer) {
      this._moveSmallLayer(layer, _layerSet.smallIndexLayer)
    }
    // 如果largeIndexLayers长度大于0
    if (_layerSet.largeIndexLayers.length > 0) {
      this._moveLargeLayers(layer, _layerSet.largeIndexLayers)
    }
    // 更新图层顺序
    layer._updateIndex()
    for (let i = 0; i < _layerSet.largeIndexLayers.length; i++) {
      if (_layerSet.largeIndexLayers[i].id !== layer.id) {
        _layerSet.largeIndexLayers[i]._updateIndex()
      }
    }
    // 更新Map中的图层实际位置
    let _index = undefined
    let _layer
    for (let i = 0; i < this.layers.items.length; i++) {
      if (this.layers.items[i].id === layer.id) {
        _index = i
        break
      }
    }
    if (_index !== undefined) {
      _layer = this.layers.items.splice(_index, 1)[0]
      this.layers.items.splice(index, 0, _layer)
    }
  }

  dispatchEvent(type, data, propagate) {
    this.fire(type, data, propagate)
    this.layers.fire(type, data, propagate)
    return this
  }

  _loadLayers() {
    this.layers.forEach((layer) => {
      this.dispatchEvent(
        MapEventType.layerAdd,
        new LayerEvent({
          type: MapEventType.layerAdd,
          target: this,
          layer
        })
      )
    })
    return this
  }

  /**
   * 设置子图层的逻辑index和realIndex
   * @private
   * @param {Object} layer 图层对象
   * @param {Number} realIndex realIndex值
   * */
  _setSubLayerIndex(layer, realIndex) {
    for (let i = 0; i < layer.layers.length; i++) {
      // 指定子图层逻辑顺序
      layer.layers[i].index = i
      // 指定子图层实际顺序
      layer.layers[i]._realIndex = realIndex + i + 1
    }
  }

  /**
   * 设置图层的实际顺序
   * @private
   * @param {Object} layer 图层对象
   * @param {Number} realIndex 从哪个index开始累加
   * */
  _setLayerAndSubLayer(layer, realIndex) {
    // 是组图层,则设置组图层的子图层的顺序
    if (layer.type === LayerType.group) {
      this._setSubLayerIndex(layer, realIndex)
    } else {
      layer._realIndex = realIndex + 1
    }
  }

  /**
   * 增加图层的realIndex对象
   * @private
   * @param {Object} layer 图层对象
   * @param {Number} addIndex 要增加的index
   * */
  _addLayerRealIndex(layer, addIndex) {
    // 是组图层
    if (layer.type === LayerType.group) {
      for (let i = 0; i < layer.layers.length; i++) {
        // 指定子图层实际顺序
        layer.layers[i]._realIndex += addIndex
      }
    } else {
      layer._realIndex += addIndex
    }
  }

  /**
   * 获取图层中最大的realIndex值
   * @private
   * @param {Array} layers 图层数组
   * @return {Number} 最大的realIndex值
   * */
  _getMaxRealIndexInLayers(layers) {
    let maxRealIndex = 0
    for (let i = 0; i < layers.length; i++) {
      if (layers[i]._realIndex > maxRealIndex) {
        maxRealIndex = layers[i]._realIndex
      }
    }
    return maxRealIndex
  }

  /**
   * 获取图层中最小的realIndex值
   * @private
   * @param {Array} layers 图层数组
   * @return {Number} 最小的realIndex值
   * */
  _getMinRealIndexInLayers(layers) {
    let minRealIndex = 0
    if (layers.length > 0) {
      minRealIndex = layers[0]._realIndex
    }
    for (let i = 0; i < layers.length; i++) {
      if (layers[i]._realIndex < minRealIndex) {
        minRealIndex = layers[i]._realIndex
      }
    }
    return minRealIndex
  }

  /**
   * 获取图层组中逻辑index最小的图层
   * @private
   * @param {Array} layers 图层数组
   * @return {Object} 逻辑index最小的图层
   * */
  _getMinIndexLayer(layers) {
    let smallerLargeLayer = undefined
    for (let i = 0; i < layers.length; i++) {
      if (!smallerLargeLayer) {
        smallerLargeLayer = layers[i]
      } else if (smallerLargeLayer.index > layers[i].index) {
        smallerLargeLayer = layers[i]
      }
    }
    return smallerLargeLayer
  }

  /**
   * 获取图层的realIndex
   * @private
   * @param {Object} layer 图层对象
   * @param {String} type 获取的方式
   * @return {Number} 图层的realIndex
   * */
  _getRealIndexInLayer(layer, type) {
    let _layerRealIndex = 0
    if (layer.type === LayerType.group) {
      if (type === 'max') {
        _layerRealIndex = this._getMaxRealIndexInLayers(layer.layers)
      } else {
        _layerRealIndex = this._getMinRealIndexInLayers(layer.layers)
      }
    } else {
      _layerRealIndex = layer._realIndex
    }
    return _layerRealIndex
  }

  /**
   * 增加逻辑index大于当前图层的图层逻辑index和realIndex
   * @private
   * @param {Object} layer 当前图层对象
   * @param {Array} largeIndexLayers 增加逻辑index大于当前图层的图层数组
   * */
  _moveLargeLayers(layer, largeIndexLayers) {
    // 获取当前图层的最大realIndex
    const _layerRealIndex = this._getRealIndexInLayer(layer, 'max')
    // 获取largeIndexLayers中index最小的图层
    const smallerLargeLayer = this._getMinIndexLayer(largeIndexLayers)
    // 获取smallerLargeLayer的最小realIndex
    const _smallerRealIndex = this._getRealIndexInLayer(
      smallerLargeLayer,
      'min'
    )
    // smallerLargeLayer的逻辑index小于当前图层的逻辑index
    // 所有largeIndexLayers的逻辑index加1
    if (smallerLargeLayer.index <= layer.index) {
      for (let i = 0; i < largeIndexLayers.length; i++) {
        // if (largeIndexLayers[i].id !== layer.id) largeIndexLayers[i].index++
      }
    }
    // smallerLargeLayer的最小realIndex小于当前图层的最大realIndex
    // 所有largeIndexLayers的realIndex加_layerRealIndex - _smallerRealIndex + 1
    if (_smallerRealIndex < _layerRealIndex) {
      for (let i = 0; i < largeIndexLayers.length; i++) {
        this._addLayerRealIndex(
          largeIndexLayers[i],
          _layerRealIndex - _smallerRealIndex + 1
        )
      }
    }
  }

  /**
   * 如果当前图层对象和摸一个图层的逻辑index相等,则将当前图层向后移动一位
   * @private
   * @param {Object} layer 当前图层对象
   * @param {Object} equalIndexLayer 和当前图层对象逻辑index相等的图层
   * */
  _moveEqualLayer(layer, equalIndexLayer) {
    // 逻辑顺序加1
    // layer.index++
    let _realIndex = 0
    // index相等的图层不是组图层
    if (equalIndexLayer.type !== LayerType.group) {
      _realIndex = equalIndexLayer._realIndex
    }
    // index相等的图层是组图层
    else {
      // 找到其中最大的realIndex
      _realIndex = this._getMaxRealIndexInLayers(equalIndexLayer.layers)
    }
    this._setLayerAndSubLayer(layer, _realIndex)
  }

  /**
   * 如果当前图层的realIndex小于等于离的最近的
   * 图层的realIndex(该图层的逻辑index和当前图层的逻辑index最接近,但不相等,图层类型为组图层)
   * 则增加当前图层的realIndex,如果大于,则直接设置
   * @private
   * @param {Object} layer 当前图层对象
   * @param {Object} smallIndexLayer 里的最近的图层对象
   * */
  _moveSmallLayer(layer, smallIndexLayer) {
    let _realIndex
    if (smallIndexLayer.type === LayerType.group) {
      let sIndex = 0
      // 找到其中最大的realIndex
      _realIndex = this._getMaxRealIndexInLayers(smallIndexLayer.layers)
      for (let i = 0; i < smallIndexLayer.layers.length; i++) {
        if (smallIndexLayer.layers[i]._realIndex > sIndex) {
          sIndex = smallIndexLayer.layers[i]._realIndex
        }
      }
    } else {
      _realIndex = smallIndexLayer._realIndex
    }
    if (_realIndex >= layer.index) {
      this._setLayerAndSubLayer(layer, _realIndex)
    } else {
      this._setLayerAndSubLayer(layer, layer.index - 1)
    }
  }

  /**
   * 获取逻辑index小于、等于和大于当前图层的图层
   * @private
   * @param {Object} layer 当前图层
   * @return {Object} 图层集合
   * */
  _getSmallEqualLargeLayers(layer) {
    // index小于当前图层的图层
    let smallIndexLayer = undefined
    // index等于当前图层的图层
    let equalIndexLayer = undefined
    // index大于当前图层的图层数组
    const largeIndexLayers = []
    // 遍历当前数组,将图层分为index小于当前图层、等于当前图层和大于当前图层两组
    for (let i = 0; i < this.layers.items.length; i++) {
      if (this.layers.items[i].index < layer.index) {
        if (!smallIndexLayer) {
          smallIndexLayer = this.layers.items[i]
        } else if (smallIndexLayer.index < this.layers.items[i].index) {
          smallIndexLayer = this.layers.items[i]
        }
      } else if (
        this.layers.items[i].index === layer.index &&
        this.layers.items[i].id !== layer.id
      ) {
        equalIndexLayer = this.layers.items[i]
      } else {
        largeIndexLayers.push(this.layers.items[i])
      }
    }

    return {
      smallIndexLayer,
      equalIndexLayer,
      largeIndexLayers
    }
  }

  /**
   * 设置图层在当前图层组中的顺序
   * @private
   * @param {Object} layer 添加的图层
   * */
  _setLayerIndex(layer) {
    let _realIndex = 0
    // 没有指定顺序,则按找先来后到的顺序排列
    if (layer.index === undefined) {
      // 指定逻辑顺序
      layer.index = this.layers.items.length
      // 图层数量为0
      if (this.layers.items.length === 0) {
        this._setLayerAndSubLayer(layer, layer.index - 1)
      }
      // 图层数量大于0,则在上一个图层的基础上加一
      else if (this.layers.items.length > 0) {
        // 找到上一个图层
        const prevLayer = this.layers.items[this.layers.items.length - 1]

        // 上一个图层不是组图层
        if (prevLayer.type !== LayerType.group) {
          _realIndex = prevLayer._realIndex
        }
        // 上一个图层是组图层
        else {
          _realIndex = this._getMaxRealIndexInLayers(prevLayer.layers)
        }

        // 如果上一个图层不是是graphic layer,则该图层在最上层。
        // 如果上一个图层是graphic layer,graphicLayer在最上层,该图层在graphicLayer下。
        if (prevLayer.type !== LayerType.graphics) {
          this._setLayerAndSubLayer(layer, _realIndex)
        } else {
          this._setLayerAndSubLayer(layer, _realIndex - 1)
          this._setLayerAndSubLayer(prevLayer, _realIndex)
        }
      }
    }
    // 指定图层的index
    else {
      // 设置index
      this._setLayerAndSubLayer(layer, layer.index - 1)
      const _layerSet = this._getSmallEqualLargeLayers(layer)
      // 如果equalIndexLayer存在
      if (_layerSet.equalIndexLayer) {
        this._moveEqualLayer(layer, _layerSet.equalIndexLayer)
      }
      // 如果smallIndexLayer存在
      else if (_layerSet.smallIndexLayer) {
        this._moveSmallLayer(layer, _layerSet.smallIndexLayer)
      }
      if (_layerSet.largeIndexLayers.length > 0) {
        this._moveLargeLayers(layer, _layerSet.largeIndexLayers)
      }
    }
  }

  _loadBasemap() {
    this._haveView = true
    if (this._basemap) {
      this._addBaseLayers()
    }
  }

  _addBaseLayers() {
    if (this._basemap._baseLayers) {
      for (let i = 0; i < this._basemap._baseLayers.items.length; i++) {
        const layer = this._basemap._baseLayers.items[i]
        if (!layer.loaded) {
          layer._isBasemapLayer = true
          this.add(layer)
        } else {
          this._basemap._baseLayers.splice(i, 1)
          i--
        }
      }
    }
  }

  _removeBaseLayers(layer) {
    if (layer) {
      layer.destroy()
      this.layers.remove(layer)
      // 删除allLayers中的图层
      this.allLayers.remove(layer)
      // 删除关联的子图层
      let _allLayers = [].concat(this.allLayers.items)
      for (let i = 0; i < _allLayers.length; i++) {
        if (_allLayers[i] instanceof SubLayer) {
          const _parentLayer = _allLayers[i].layer
          if (_parentLayer && _parentLayer.id && _parentLayer.id === layer.id) {
            this.allLayers.remove(_allLayers[i])
          }
        }
      }
      _allLayers = undefined
    }
  }

  _setBasemap(value) {
    // map上有_basemap,并且value不为空或undefined,则是该basemap需要初始挂载事件
    if (!this._basemap && value) {
      value.on('destroyed', () => {
        if (this._basemap._baseLayers) {
          this._basemap._baseLayers.forEach((baseLayer) => {
            baseLayer._isBasemapLayer = false
            this.remove(baseLayer)
          })
        }
        this._basemap = null
      })
    }
    // 如果value不为空或undefined,或者this._basemap不为空(即没有被销毁),则将新的value赋值给map的basemap
    if (value) {
      if (this._haveView) {
        if (this._basemap && this._basemap._baseLayers) {
          this._basemap._baseLayers.forEach((baseLayer) => {
            baseLayer._isBasemapLayer = false
          })
          this._canResetView = false
          this.removeMany(this._basemap._baseLayers.items)
          this._canResetView = true
        }
        this._basemap = value
        this._addBaseLayers()
      }
    } else {
      this._basemap.spatialReference = null
      if (this._basemap && this._basemap._baseLayers) {
        this._basemap._baseLayers.forEach((baseLayer) => {
          baseLayer._isBasemapLayer = false
        })
        this.removeMany(this._basemap._baseLayers.items)
      }
      this._basemap = value
    }
  }
}

Object.defineProperties(Map.prototype, {
  basemap: {
    get() {
      return this._basemap
    },
    set(value) {
      this._setBasemap(value)
    }
  }
})

export default Map
Zondy.Map = Map
构造函数
成员变量
方法
事件