<template>
    <div class="im-popover">
        <template>
            <transition
                :name="transition"
                @after-enter="handleAfterEnter"
                @after-leave="handleAfterLeave"
            >
                <div
                    :class="['popper', popperClass]"
                    ref="ref_popper"
                    v-show="!disabled && showPopper"
                    @mouseleave="onHidePopper"
                    @mouseenter="onShowPopper"
                >
                    <slot></slot>
                </div>
            </transition>
        </template>
        <div
            class="reference_wrap"
            ref="wrapper"
            @mouseleave="onHidePopper"
            @mouseenter="onShowPopper"
            :showPopper="showPopper"
        >
            <slot name="reference"></slot>
        </div>
    </div>
</template>

<script>
import popper from './popper';
export default {
    emits: ['after-enter', 'after-leave'],
    name: 'im-popper',
    mixins: [popper],
    props: {
        transition: {
            type: String,
            default: 'fade-in-linear'
        },
        //  for true express hover exist reference layer showPopper for true
        hover: {
            type: Boolean,
            default: false
        },
        //  for true express hover exist popper layer showPopper for true
        popperHover: {
            type: Boolean,
            default: false
        },
        disabled: {
            type: Boolean,
            default: false
        },
        popperClass: {
            type: String,
            default: ''
        }
    },
    watch: {
        disabled(val) {
            if (val) this.showPopper = false;
        }
    },
    data: function () {
        return {
            _reference: null
        };
    },
    methods: {
        handleAfterEnter() {
            this.$emit('after-enter');
        },
        onShowPopper() {
            if (!this.hover) {
                return null;
            }
            if (this.popperHover) {
                window.clearTimeout(this.timerLeave);
            }
            this.showPopper = true;
        },
        onHidePopper() {
            if (!this.hover) {
                return null;
            }
            if (this.popperHover) {
                this.timerLeave = setTimeout(() => {
                    this.showPopper = false;
                }, 100);
            } else {
                this.showPopper = false;
            }
        },
        handleAfterLeave() {
            this.doDestroy();
            this.$emit('after-leave');
        },
        onDocumentClick() {
            window.document.addEventListener(
                'click',
                this.clickDocument,
                false
            );
        },
        clickDocument(e) {
            let reference = (this.referenceEle =
                this.reference || this.$refs.ref_reference);
            const popper = this.popper || this.$refs.ref_popper;
            if (!reference && this.$refs.wrapper.children) {
                reference = this.referenceEle = this.$refs.wrapper.children[0];
            }
            if (
                !this.$el ||
                !reference ||
                this.$el.contains(e.target) ||
                reference.contains(e.target) ||
                !popper ||
                popper.contains(e.target)
            )
                return;
            this.showPopper = false;
        }
    },
    mounted() {
        let reference = (this.referenceEle =
            this.reference || this.$refs.ref_reference);
        if (!reference && this.$refs.wrapper.children) {
            reference = this.referenceEle = this.$refs.wrapper.children[0];
        }
        this._reference = reference;

        reference.addEventListener('click', this.toggle, false);

        this.onDocumentClick();
        if (this.disabled) this.showPopper = false;
    },
    beforeUnmount() {
        this._reference &&
            this._reference.removeEventListener('click', this.toggle, false);
        window.document.removeEventListener('click', this.clickDocument, false);
    }
};
</script>

<style lang="scss">
@use './transition' as *;
.popper {
    z-index: 99999;
    .arrow,
    .arrow::before {
        position: absolute;
        width: 8px;
        height: 8px;
        background: inherit;
    }

    .arrow {
        visibility: hidden;
    }
    .arrow::before {
        visibility: visible;
        content: '';
        transform: rotate(45deg);
        border: 1px solid;
        border-color: inherit;
    }
}
.popper[data-popper-placement^='top'] > .arrow {
    bottom: -4px;
    border-top-color: transparent;
    border-left-color: transparent;
}

.popper[data-popper-placement^='bottom'] > .arrow {
    top: -4px;
    border-right-color: transparent;
    border-bottom-color: transparent;
}

.popper[data-popper-placement^='left'] > .arrow {
    right: -4px;
    border-left-color: transparent;
    border-bottom-color: transparent;
}

.popper[data-popper-placement^='right'] > .arrow {
    left: -4px;
    border-top-color: transparent;
    border-right-color: transparent;
}
</style>
