<script>
import PropTypes from '../../_util/vue-types'
import Trigger from '../../trigger'
import placements from './placements'
import { hasProp } from '../../_util/props-util'
import BaseMixin from '../../_util/BaseMixin'
import { cloneElement, getEvents } from '../../_util/vnode'

export default {
  mixins: [BaseMixin],
  props: {
    minOverlayWidthMatchTrigger: PropTypes.bool.def(true),
    prefixCls: PropTypes.string.def('rc-dropdown'),
    transitionName: PropTypes.string,
    overlayClassName: PropTypes.string.def(''),
    animation: PropTypes.any,
    align: PropTypes.object,
    overlayStyle: PropTypes.object.def({}),
    placement: PropTypes.string.def('bottomLeft'),
    trigger: PropTypes.array.def(['hover']),
    showAction: PropTypes.array.def([]),
    hideAction: PropTypes.array.def([]),
    getPopupContainer: PropTypes.func,
    visible: PropTypes.bool,
    defaultVisible: PropTypes.bool.def(false),
    mouseEnterDelay: PropTypes.number.def(0.15),
    mouseLeaveDelay: PropTypes.number.def(0.1),
  },
  data () {
    let sVisible = this.defaultVisible
    if (hasProp(this, 'visible')) {
      sVisible = this.visible
    }
    return {
      sVisible,
    }
  },
  watch: {
    visible (val) {
      if (val !== undefined) {
        this.setState({
          sVisible: val,
        })
      }
    },
  },
  methods: {
    onClick (e) {
      // do no call onVisibleChange, if you need click to hide, use onClick and control visible
      if (!hasProp(this, 'visible')) {
        this.setState({
          sVisible: false,
        })
      }
      this.$emit('overlayClick', e)
      if (this.childOriginEvents.click) {
        this.childOriginEvents.click(e)
      }
    },

    onVisibleChange (visible) {
      if (!hasProp(this, 'visible')) {
        this.setState({
          sVisible: visible,
        })
      }
      this.__emit('visibleChange', visible)
    },

    getMenuElement () {
      const child = this.$slots.overlay[0]
      const events = getEvents(child)
      if (!events._ANT_DROPDOWN_EVENT_HACK) {
        this.childOriginEvents = events
      }
      const { prefixCls } = this.$props
      const extraOverlayProps = {
        prefixCls: `${prefixCls}-menu`,
      }
      const overlay = this.$slots.overlay[0]
      return cloneElement(overlay, {
        props: extraOverlayProps,
        on: {
          click: this.onClick,
          _ANT_DROPDOWN_EVENT_HACK: () => {},
        },
      })
    },

    getPopupDomNode () {
      return this.$refs.trigger.getPopupDomNode()
    },

    afterVisibleChange (visible) {
      if (visible && this.$props.minOverlayWidthMatchTrigger) {
        const overlayNode = this.getPopupDomNode()
        const rootNode = this.$el
        if (rootNode && overlayNode && rootNode.offsetWidth > overlayNode.offsetWidth) {
          overlayNode.style.width = `${rootNode.offsetWidth}px`
          if (this.$refs.trigger &&
            this.$refs.trigger._component &&
            this.$refs.trigger._component.alignInstance) {
            this.$refs.trigger._component.alignInstance.forceAlign()
          }
        }
      }
    },
  },

  render () {
    const {
      prefixCls,
      transitionName, animation,
      align, placement, getPopupContainer,
      showAction, hideAction,
      overlayClassName, overlayStyle,
      trigger, ...otherProps
    } = this.$props

    const triggerProps = {
      props: {
        ...otherProps,
        prefixCls,
        popupClassName: overlayClassName,
        popupStyle: overlayStyle,
        builtinPlacements: placements,
        action: trigger,
        showAction,
        hideAction,
        popupPlacement: placement,
        popupAlign: align,
        popupTransitionName: transitionName,
        popupAnimation: animation,
        popupVisible: this.sVisible,
        afterPopupVisibleChange: this.afterVisibleChange,
        getPopupContainer: getPopupContainer,
      },
      on: {
        popupVisibleChange: this.onVisibleChange,
      },
      ref: 'trigger',
    }
    const child = this.$slots.default && this.$slots.default[0]
    return (
      <Trigger {...triggerProps}>
        {child && !child.tag
          ? <span>{child}</span>
          : child}
        <template slot='popup'>
          {this.$slots.overlay && this.getMenuElement()}
        </template>
      </Trigger>
    )
  },
}

</script>
