import {PopupManager} from 'element-ui/lib/utils/popup'

import PopperJS from 'popper.js'
//import * as PopperJS from '@popperjs/core'

const POPPER_VERSION = 'v1'

if (POPPER_VERSION === 'v2') {
    console.warn = () => ({})
}

const stop = e => e.stopPropagation()

const defaultOptions = () => {
    return POPPER_VERSION === 'v2' ? {modifiers: []} : {modifiers: {computeStyle: {gpuAcceleration: false}}}
}

export default {
    props: {
        transformOrigin: {type: [Boolean, String], default: true},
        placement: {type: String, default: 'bottom'},
        boundariesPadding: {type: Number, default: 5},
        reference: {},
        popper: {},
        offset: {type: Number, default: POPPER_VERSION === 'v2' ? 12 : 0},
        value: Boolean,
        visibleArrow: {type: Boolean, default: true},
        arrowOffset: {type: Number, default: 35},
        appendToBody: {type: Boolean, default: true},
        popperOptions: {type: Object, default: defaultOptions}
    },

    data() {
        return {
            showPopper: this.value
        }
    },

    watch: {
        value: {
            immediate: true,
            handler(val) {
                this.showPopper = val
                this.$emit('input', val)
                if (this.disabled) return
                val ? this.updatePopper() : this.destroyPopper()
            }
        }
    },

    methods: {
        createPopper() {
            if (!/^(top|bottom|left|right)(-start|-end)?$/g.test(this.placement)) {
                return
            }

            const options = this.popperOptions
            const popper = this.popperElm = this.popperElm || this.popper || this.$refs.popper
            let reference = this.referenceElm = this.referenceElm || this.reference || this.$refs.reference

            if (!reference && this.$slots.reference && this.$slots.reference[0]) {
                reference = this.referenceElm = this.$slots.reference[0].elm
            }

            if (!popper || !reference) return

            if (this.popperJS && this.popperJS.hasOwnProperty('destroy')) {
                this.popperJS.destroy()
            }

            if (this.appendToBody) document.body.appendChild(this.popperElm)
            if (this.visibleArrow) this.setArrow()
            this.setOffset(options)

            options.placement = this.placement
            const createEvent = POPPER_VERSION === 'v2' ? 'onFirstUpdate' : 'onCreate'
            options[createEvent] = () => {
                this.$emit('created', this)
                this.resetTransformOrigin()
                this.$nextTick(this.updatePopper)
            }

            this.popperJS = POPPER_VERSION === 'v2' ?
                PopperJS.createPopper(reference, popper, options)
                : new PopperJS(reference, popper, options)

            popper.style.zIndex = PopupManager.nextZIndex()
            this.popperElm.addEventListener('click', stop)
        },

        updatePopper() {
            const popper = this.popperJS

            if (!popper) return this.createPopper()

            popper.update()
            this.popperElm.style.zIndex = PopupManager.nextZIndex()
        },

        doDestroy(forceDestroy) {
            if (!this.popperJS || (this.showPopper && !forceDestroy)) return
            this.popperJS.destroy()
            this.popperJS = null
        },

        destroyPopper() {
            this.popperJS && this.resetTransformOrigin()
        },

        setOffset(options) {
            if (POPPER_VERSION === 'v2') {
                const modifier = this.popperOptions.modifiers.find(modifier => modifier.name === 'offset'),
                    offset = {offset: [0, this.offset]}

                if (!modifier) {
                    this.popperOptions.modifiers.push({name: 'offset', options: offset})
                }
                else modifier.options = offset
            }
            else {
                if (!options.modifiers.offset) {
                    options.modifiers.offset = {}
                }
                options.modifiers.offset.offset = this.offset
            }
        },

        setArrow() {
            if (this.appended) return
            this.appended = true

            const arrow = document.createElement('div')
            arrow.className = 'popper__arrow'
            arrow.setAttribute(POPPER_VERSION === 'v2' ? 'data-popper-arrow' : 'x-arrow', '')
            const attributes = this.popperElm.attributes
            const key = Object.keys(attributes).find(key => /^_v-/.test(attributes[key].name))
            if (key) arrow.setAttribute(attributes[key].name, '')

            this.popperElm.appendChild(arrow)
        },

        resetTransformOrigin() {
            if (!this.transformOrigin) return
            const placementMap = {top: 'bottom', bottom: 'top', left: 'right', right: 'left'}
            const attr = POPPER_VERSION === 'v2' ? 'data-popper-placement' : 'x-placement'
            const placement = this.popperElm.getAttribute(attr).split('-')[0]
            const origin = placementMap[placement]
            this.popperElm.style.transformOrigin =
                typeof this.transformOrigin === 'string'
                    ? this.transformOrigin
                    : ['top', 'bottom'].includes(placement) ? `center ${origin}` : `${origin} center`
        }
    },

    deactivated() {
        this.$options.beforeDestroy[0].call(this)
    },

    beforeDestroy() {
        this.doDestroy(true)
        if (this.popperElm && this.popperElm.parentNode === document.body) {
            this.popperElm.removeEventListener('click', stop)
            document.body.removeChild(this.popperElm)
        }
    }
}
