/**
 * @description  地图懒加载
 * @author       刘晖(liuh@microvideo.cn)
 * @date         2021/11/9 16:31
 */
 import {
  patchIOS11Geo
} from './polyfill';
import {
  initMapDefaultConfig,
  mapDefaultPlugins
} from '../config/map-default-config';
import AMapLoader from '@amap/amap-jsapi-loader';

const defaultConfig = initMapDefaultConfig

export default class LazyMapLoader {

  constructor(mapConfig) {
      let plugin = mapDefaultPlugins
      if (mapConfig.plugin) {
          plugin = [...mapDefaultPlugins, ...mapConfig.plugin]
      }

      this.config = Object.assign(defaultConfig, mapConfig, { plugin });

      if (this.config.v != '2.0' && this.config.v != '1.4.15') {
          alert("地图版本不正确，仅支持 '2.0' 和 '1.4.15'版本,请更换版本! ")
          return
      }
      window._AMapSecurityConfig = {
          securityJsCode: this.config.securityJsCode
      }
      this.mapDocument = document;
      this.mapWindow = window;
      this.mapQueueEvents = [patchIOS11Geo];
  }
  /**
   * 地图加载 
   * JSAPI Loader https://lbs.amap.com/api/jsapi-v2/guide/abc/load
   * @returns AMap
   */
  mapLoad() {
      const mapPrefixReg = /^AMap./;
      const config = this.config;
      const plugins = [];

      if (config.plugin && config.plugin.length > 0) {
          config.plugin.forEach(item => {
              const prefixName = (mapPrefixReg.test(item)) ? item : 'AMap.' + item;
              !plugins.includes(prefixName) && plugins.push(prefixName);
          });
      }

      return new Promise((resolve, reject) => {
          AMapLoader.load({
              key: config.key, // 申请好的Web端开发者Key，首次调用 load 时必填
              version: config.v, // 指定要加载的 JSAPI 的版本，缺省时默认为 1.4.15
              plugins: plugins, // 需要使用的的插件列表，如比例尺'AMap.Scale'等
              AMapUI: { // 是否加载 AMapUI，缺省不加载
                  version: this.config.uiVersion, // AMapUI 版本
                  plugins: [], // 需要加载的 AMapUI ui插件
              },
          }).then((AMap) => {
              if (this.AMap) {
                  resolve(AMap)
                  return
              }
              // 初次加载
              this.AMap = AMap

              while (this.mapQueueEvents.length) {
                  this.mapQueueEvents.pop().apply();
              }
              
              resolve(AMap)
          }).catch(e => {
              reject(e);
          })
      })

  }
  /**
   * AMap懒加载
   * @returns Promise
   */
  lazyMapLoad() {
      if (this.mapWindow.AMap && this.mapWindow.AMap.Map)
          return this.lazyLoadUIAMap();

      if (this.scriptLoadingPromise) return this.scriptLoadingPromise;

      const script = this.mapDocument.createElement('script');
      script.type = 'text/javascript';
      script.async = true;
      script.defer = true;
      script.src = this.getScriptSrc();

      const UIPromise = this.config.uiVersion ? this.lazyLoadUIAMap() : null;
      this.scriptLoadingPromise = new Promise((resolve, reject) => {
          this.mapWindow['amapInitComponent'] = () => {
              while (this.mapQueueEvents.length) {
                  this.mapQueueEvents.pop().apply();
              }
              if (UIPromise) {
                  UIPromise.then(() => {
                      window.initAMapUI();
                      setTimeout(resolve)
                  })
              } else {
                  return resolve();
              }
          };
          script.onerror = err => reject(err);
      });

      this.mapDocument.head.appendChild(script);

      return this.scriptLoadingPromise;
  }
  /**
   * AMapUI 懒加载
   * @returns Promise
   */
  lazyLoadUIAMap() {
      if (!this.config.uiVersion || window.AMapUI)
          return Promise.resolve();
      return new Promise((resolve, reject) => {
          const UIScript = document.createElement('script');
          const [versionMain, versionSub] = this.config.uiVersion.split('.');
          if (versionMain === undefined || versionSub === undefined) {
              console.log('AMapUI版本不正确，请检查版本；当前版本为：' + this.config.uiVersion);
              return;
          }
          let src = `https://webapi.amap.com/ui/${versionMain}.${versionSub}/main-async.js`;
          UIScript.src = src;
          UIScript.type = 'text/javascript';
          UIScript.async = true;
          this.mapDocument.head.appendChild(UIScript);
          UIScript.onload = () => {
              setTimeout(resolve, 0)
          };
          UIScript.onerror = () => reject();
      })

  }


  getScriptSrc() {
      const mapPrefixReg = /^AMap./;
      const config = this.config;
      const paramKeys = ['v', 'key', 'plugin', 'callback'];
      if (config.plugin && config.plugin.length > 0) {
          const plugins = [];
          config.plugin.forEach(item => {

              const prefixName = (mapPrefixReg.test(item)) ? item : 'AMap.' + item;

              !plugins.includes(prefixName) && plugins.push(prefixName);
          });
          config.plugin = plugins;
      }
      const params = Object.keys(config)
          .filter(k => ~paramKeys.indexOf(k))
          .filter(k => config[k] != null)
          .filter(k => {
              return !Array.isArray(config[k]) ||
                  (Array.isArray(config[k]) && config[k].length > 0);
          })
          .map(k => {
              let v = config[k];
              if (Array.isArray(v)) return {
                  key: k,
                  value: v.join(',')
              };
              return {
                  key: k,
                  value: v
              };
          })
          .map(entry => `${entry.key}=${entry.value}`)
          .join('&');
      return `https://webapi.amap.com/maps?${params}`;
  }

}