text: import upperCamelCase from "uppercamelcase";
  import { commonConvertMap } from "../utils/convert-helper";
  import eventHelper from "../utils/event-helper";
  import { lazyAMapApiLoaderInstance } from "../services/injected-amap-api-instance";
  import CONSTANTS from "../utils/constant";
  import Vue2AMap from "../";
  
  export default {
    data() {
      return {
        unwatchFns: []
      };
    },
  
    mounted() {
      if (lazyAMapApiLoaderInstance) {
        lazyAMapApiLoaderInstance.load().then(() => {
          this.__contextReady &&
            this.__contextReady.call(this, this.convertProps());
        });
      }
      this.$amap = this.$amap || this.$parent.$amap;
      if (this.$amap) {
        this.register();
      } else {
        this.$on(CONSTANTS.AMAP_READY_EVENT, map => {
          this.$amap = map;
          this.register();
        });
      }
    },
  
    destroyed() {
      this.unregisterEvents();
      if (!this.$amapComponent) return;
  
      this.$amapComponent.setMap && this.$amapComponent.setMap(null);
      this.$amapComponent.close && this.$amapComponent.close();
      this.$amapComponent.editor && this.$amapComponent.editor.close();
      this.unwatchFns.forEach(item => item());
      this.unwatchFns = [];
    },
  
    methods: {
      getHandlerFun(prop) {
        if (this.handlers && this.handlers[prop]) {
          return this.handlers[prop];
        }
  
        return (
          this.$amapComponent[`set${upperCamelCase(prop)}`] ||
          this.$amapComponent.setOptions
        );
      },
  
      convertProps() {
        const props = {};
        if (this.$amap) props.map = this.$amap;
        const {
          $options: { propsData = {} },
          propsRedirect
        } = this;
        return Object.keys(propsData).reduce((res, _key) => {
          let key = _key;
          let propsValue = this.convertSignalProp(key, propsData[key]);
          if (propsValue === undefined) return res;
          if (propsRedirect && propsRedirect[_key]) key = propsRedirect[key];
          props[key] = propsValue;
          return res;
        }, props);
      },
  
      convertSignalProp(key, sourceData) {
        let converter = "";
        let type = "";
  
        if (this.amapTagName) {
          try {
            const name = upperCamelCase(this.amapTagName).replace(/^El/, "");
            const componentConfig = Vue2AMap[name] || "";
  
            type = componentConfig.props[key].$type;
            converter = commonConvertMap[type];
          } catch (e) {}
        }
  
        if (type && converter) {
          return converter(sourceData);
        } else if (this.converters && this.converters[key]) {
          return this.converters[key].call(this, sourceData);
        } else {
          const convertFn = commonConvertMap[key];
          if (convertFn) return convertFn(sourceData);
          return sourceData;
        }
      },
  
      registerEvents() {
        this.setEditorEvents && this.setEditorEvents();
        if (!this.$options.propsData) return;
        if (this.$options.propsData.events) {
          for (let eventName in this.events) {
            eventHelper.addListener(
              this.$amapComponent,
              eventName,
              this.events[eventName]
            );
          }
        }
  
        if (this.$options.propsData.onceEvents) {
          for (let eventName in this.onceEvents) {
            eventHelper.addListenerOnce(
              this.$amapComponent,
              eventName,
              this.onceEvents[eventName]
            );
          }
        }
      },
  
      unregisterEvents() {
        eventHelper.clearListeners(this.$amapComponent);
      },
  
      setPropWatchers() {
        const {
          propsRedirect,
          $options: { propsData = {} }
        } = this;
  
        Object.keys(propsData).forEach(prop => {
          let handleProp = prop;
          if (propsRedirect && propsRedirect[prop])
            handleProp = propsRedirect[prop];
          let handleFun = this.getHandlerFun(handleProp);
          if (!handleFun && prop !== "events") return;
  
          // watch props
          const unwatch = this.$watch(prop, nv => {
            if (prop === "events") {
              this.unregisterEvents();
              this.registerEvents();
              return;
            }
            if (handleFun && handleFun === this.$amapComponent.setOptions) {
              return handleFun.call(this.$amapComponent, {
                [handleProp]: this.convertSignalProp(prop, nv)
              });
            }
  
            handleFun.call(this.$amapComponent, this.convertSignalProp(prop, nv));
          });
  
          // collect watchers for destroyed
          this.unwatchFns.push(unwatch);
        });
      },
  
      registerToManager() {
        let manager = this.amapManager || this.$parent.amapManager;
        if (manager && this.vid !== undefined) {
          manager.setComponent(this.vid, this.$amapComponent);
        }
      },
  
      // some prop can not init by initial created methods
      initProps() {
        const props = ["editable", "visible"];
  
        props.forEach(propStr => {
          if (this[propStr] !== undefined) {
            const handleFun = this.getHandlerFun(propStr);
            handleFun &&
              handleFun.call(
                this.$amapComponent,
                this.convertSignalProp(propStr, this[propStr])
              );
          }
        });
  
        // this.printReactiveProp();
      },
  
      /**
       * methods for developing
       * find reactive props
       */
      printReactiveProp() {
        Object.keys(this._props).forEach(k => {
          let fn = this.$amapComponent[`set${upperCamelCase(k)}`];
          if (fn) {
            console.log(k);
          }
        });
      },
  
      register() {
        const res =
          this.__initComponent && this.__initComponent(this.convertProps());
        if (res && res.then) res.then(instance => this.registerRest(instance));
        // promise
        else this.registerRest(res);
      },
  
      registerRest(instance) {
        if (!this.$amapComponent && instance) this.$amapComponent = instance;
        this.registerEvents();
        this.initProps();
        this.setPropWatchers();
        this.registerToManager();
  
        if (this.events && this.events.init)
          this.events.init(
            this.$amapComponent,
            this.$amap,
            this.amapManager || this.$parent.amapManager
          );
      },
  
      // helper method
      $$getInstance() {
        return this.$amapComponent;
      }
    }
  };
  