// 在mapboxgl.Map中添加新的方法

const addedMapUtil = {
  // base map state
  _originalMapState: null,
  // 设置初始地图状态
  _initMapState(state) {
    const { center, zoom } = state;
    if (!center || !zoom) {
      throw new Error("missing center or zoom!");
    }
    this._originalMapState = {
      zoom,
      center,
    };
  },
  // recover map
  recover() {
    // this.setCenter(this._originalMapState.center)
    // this.zoomTo(this._originalMapState.zoom)
    this.flyTo({
      center: this._originalMapState.center,
      zoom: this._originalMapState.zoom,
    });
  },
  baseMap: null,
  /**
   * @description 设置基础底图
   * @param {Object} [baseMap.sources] 底图的sources, 和mapbox style中source格式一致
   * @param {Array} [baseMap.layers] 底图的layers, 和mapbox style中layers格式一致
   * @param {Object} options style中其它的选项，例如加载一些图层需要特定的字体和雪碧图。 注意：修改sprites、icon、glyphs会导致强制更新，这种情况下可能会导致某些图层丢失
   */
  setBaseMap(baseMap, options) {
    const { sources, layers } = baseMap;
    // init map
    if (!this.baseMap) {
      this.baseMap = baseMap; // 缓存地图的source和layer
      return;
    }

    const style = this.getStyle();
    // set sources
    Object.assign(style.sources, sources);

    // set layers
    const oldLayers = style.layers;
    const firstLayer = oldLayers[0];
    if (!firstLayer) {
      style.layers.push(...layers);
    } else {
      // step1. remove old base layers
      const layerIds = this.baseMap.layers.map((layer) => layer.id);
      layerIds.forEach((layerId) => {
        const index = oldLayers.findIndex((l) => l.id === layerId);
        if (index > -1) {
          oldLayers.splice(index, 1);
        }
      });
      // step2. add new base layers to the top of old layers
      style.layers = layers.concat(oldLayers);

      // other mapbox style options. eg. glyphs and sprite
      if (options) {
        Object.assign(style, options);
      }
      this.setStyle(style);
    }
    this.baseMap = { sources, layers }; // 缓存地图的source和layer
  },
  // 获取底图的配置
  getBaseMap() {
    return this.baseMap;
  },
};

export function register(proto) {
  Object.assign(proto, addedMapUtil);
}
