const types = {
  control: {
    unload: 'removeControl'
  },
  layer: {
    unload: 'removeTileLayer'
  },
  overlay: {
    unload: 'removeOverlay'
  },
  contextMenu: {
    unload: 'removeContextMenu'
  }
}

const getParent = $component => ($component.abstract || $component.$el === $component.$children[0].$el) ? getParent($component.$parent) : $component

function destroyInstance() {
  const { unload, renderByParent, $parent } = this
  if (renderByParent) {
    $parent.reload()
  }
  unload()
}

class Mixin {
  constructor(prop) {
    this.methods = {
      ready() {
        const $parent = getParent(this.$parent)
        const mapLayers = this.mapLayers = $parent.mapLayers
        this.load()
        this.$emit('ready', {
          mapLayers
        })
      },
      transmitEvent(e) {
        this.$emit(e.type.replace(/^on/, ''), e)
      },
      reload() {
        this && this.BMap && this.$nextTick(() => {
          this.unload()
          this.$nextTick(this.load)
        })
      },
      unload() {
        const { mapLayers, originInstance } = this
        try {
          switch (prop.type) {
            case 'search':
              return originInstance.clearResults()
            case 'autoComplete':
            case 'lushu':
              return originInstance.dispose()
            case 'markerClusterer':
              return originInstance.clearMarkers()
            default:
              mapLayers[types[prop.type].unload](originInstance)
          }
        } catch (e) {
          console.log(e)
        }
      }
    }
    this.computed = {
      renderByParent() {
        return this.$parent.preventChildrenRender
      }
    }
    this.mounted = function() {
      const $parent = getParent(this.$parent)
      const mapLayers = $parent.mapLayers
      const { ready } = this
      mapLayers ? ready() : $parent.$on('ready', ready)
    }
    this.destroyed = destroyInstance
    this.beforeDestroy = destroyInstance
  }
}

export default type => new Mixin({ type })
