import upperCamelCase from 'uppercamelcase'
import { commonConvertMap } from '../utils/convert-helper'
import eventHelper from '../utils/event-helper'

export default {
  data() {
    return {
      unwatchFns: []
    }
  },

  mounted() {
    console.log('mounted')
    this.map = this.map || this.$parent.map
    if (this.map) {
      this.register()
    } else {
      this.$on('ready', map => {
        this.map = map
        this.register()
      })
    }
  },

  destroyed() {
    this.unregisterEvents()
    // if (!this.$amapComponent)
    //
    // 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
    },
    // 转换参数，遍历所有props
    convertProps() {
      const props = {}
      if (this.map) props.map = this.map
      const { $options: { propsData = {}}, propsRedirect } = this
      return Object.keys(propsData).reduce((res, _key) => {
        let key = _key
        const 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 = ''
      try {
        type = key
        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 (const eventName in this.events) {
          eventHelper.addListener(this.$amapComponent, eventName, this.events[eventName])
        }
      }
      if (this.$options.propsData.onceEvents) {
        for (const 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]
        const 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)
      })
    },

    // some prop can not init by initial created methods
    // 一些不能再created时初始化的属性
    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 => {
        const 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
      if (this.$amapComponent) {
        this.registerEvents()
        this.initProps()
        this.setPropWatchers()
        if (this.events && this.events.init) {
          this.events.init(this.$amapComponent, this.map)
        }
      }
    },

    // helper method
    $$getInstance() {
      return this.$amapComponent
    }
  }
}
