<template>
    <transition
        name="n_popup"
        @after-enter="_afterEnter"
        @after-leave="close">
        <div
            class="nus_popup"
            v-if="myIsOpen"
            v-show="myIsShow"
            :class="[wrapCla,((alignCla && 'nu_align-' + alignCla)||''), maskFlag === -1 && 'nu_hide-mask']">
            <i
                class="nu_close nu_icon"
                v-if="isCloseBtn"
                @touchstart="closePopup($event)"
                @click="closePopup($event)"
                @tap="closePopup($event)">
                &#xe608;
            </i>
            <div
                class="nu_popup-bg"
                v-if="maskFlag !== -1"
                :class="[maskFlag + '' === '1' && 'nu_mask']"
                ref="hook_bg"
                @click="_clickBg($event)"
                @tap="_clickBg($event)">
            </div>
            <div
                ref="hook_wrap"
                class="nu_content-wrap"
                :style="wrapHeight && {height:wrapHeight}">
                <div
                    class="nu_content"
                    ref="hookCont"
                    :class="[transitionCls && 'n_' + transitionCls]"
                    @click="_clickCont($event)"
                    @tap="_clickCont($event)">
                    <slot>
                        <div
                            v-if="content"
                            v-bind="myProps"
                            ref="hook_is"
                            :is="content"
                            @showChange="show()"
                            @hideChange="hide()"
                            @closePopup="closePopup"
                            @close="close"
                            @openPage="_toPage"
                            @goBackPage="_goBackPage"
                            @confirmChange="_confirm"
                            @cancelChange="_cancel">
                        </div>
                    </slot>
                </div>
            </div>
        </div>
    </transition>
</template>
<script>
/* eslint-disable max-lines */
import { initEvent, dispatchEvent, prefixEvent, callFn } from 'nimble-lib';
import attrSync from '../../../Mixins/attrSync/attrSync';
import { POPUP_EVENT } from '../../../_commons/constant';
import PopupRouter from './PopupRouter';
import confirm from '../../../Mixins/confirm';

export default {
    extends: PopupRouter,
    name: 'NuPopup',
    props: {
        /**
         * 是否显示遮罩-1不显示0透明1显示半透明
         */
        maskFlag: {
            type: [Number, String],
            default: 1
        },
        /**
         * 传入的组件参数
         */
        props: {
            type: Object
        },
        /**
         * 传入的动态组件
         */
        content: {},
        /**
         * 设置高度
         */
        isHeight: {
            type: Boolean,
            default: false
        },
        /**
         * 点击背景是否可关闭(0为不关闭；1为关闭；2为隐藏)
         */
        maskCloseFlag: {
            type: Number,
            default: 1
        },
        /**
         * 是否显示关闭按钮
         */
        isCloseBtn: {
            type: Boolean,
            default: false
        },
        /**
         * 对齐方式class名（bottom｜top｜fullScreen｜centerMiddle）
         */
        alignCla: {
            type: String,
            default: 'bottom'
        },
        /**
         * 最外层class名
         */
        wrapCla: {
            type: String,
            default: ''
        },
        /**
         * 启用动画
         */
        transition: {
            type: Boolean,
            default: true
        },
        /**
         * 过渡class名 ''|toUp|scale|toBottom|toLeft;
         * 过渡css(toUp从下向上，toBottom从上往下，scale从小到大, toLeft从右往左)
         */
        transitionCls: {
            type: String,
            default: 'toUp'
        }
    },
    data () {
        return {
            cHeight: 0,
            /**
             * 显示隐藏的标志(show|hide|null|undefined)
             */
            showFlag: null,
            /**
             * 内容组件的props（处理watch不到的情况）
             */
            myProps: this.props
        };
    },
    mixins: [attrSync('isOpen', { // 是否打开
        value: {
            type: Boolean,
            default: true
        },
        mValueChange(nowVal) {
            let _that = this;
            if (nowVal) {
                _that.myIsOpen = nowVal;
                _that._initCom();
                _that.show(true);
            } else {
                _that._clearInit();
                _that.hide();
            }
            return false;
        }
    }), attrSync('isShow', { // 是否显示
        value: {
            type: Boolean,
            default: true
        },
        myValueInit() {
            return false;
        },
        mValueChange(nowVal) {
            let _that = this;
            if (nowVal) {
                _that.myIsOpen = true;
                _that.show();
            } else {
                _that.hide();
            }
            return false;
        }
    }), confirm()],
    watch: {
        showOpen(nowVal) {
            this._setScroll(nowVal);
        },
        props(nowVal) {
            this.myProps = nowVal;
        }
    },
    created() {
        let _that = this;
        _that._resize = function () {
            _that.cHeight = null;
            if (typeof _that.timer !== 'undefined') {
                clearTimeout(_that.timer);
            }
            _that.timer = setTimeout(() => {
                _that._getWrapHeight();
            }, 20);
        };

        _that._initCom();
    },
    beforeDestroy() {
        let _that = this;
        if (_that.myIsOpen) {
            let evt = initEvent('destroy');
            _that.close(evt);
        }
        _that._setScroll(false);
    },
    mounted () {
        let _that = this;
        _that.show(true);
        _that._setScroll(_that.showOpen);
    },
    computed: {
        showOpen() {
            let _that = this;
            return _that.isOpen && _that.myIsOpen && _that.isShow && _that.myIsShow;
        },
        wrapHeight() {
            let res = '';
            if (this.isHeight) {
                let _height = this.cHeight;
                if (_height) {
                    res = _height + 'px';
                }
            }
            return res;
        }
    },
    methods: {
        /**
         * 清理初始化数据
         */
        _clearInit() {
            let _that = this;
            _that._isInit = false;
        },
        _afterEnter() {
            dispatchEvent(this.$el, prefixEvent('transitionend', true));
        },
        /**
         * 初始化
         */
        _initCom() {
            let _that = this;
            _that.hide(true);
            if (_that.isOpen) {
                _that._initDisable();
                _that._stopEvent();
                if (!_that._initEvent) {
                    _that._initEvent = true;
                    if (this.isHeight) {
                        window.addEventListener('resize', _that._resize);
                        window.addEventListener('orientationchange', _that._resize);
                    }
                }
            }
        },
        /**
         * 获取当前传入的动态组件
         * @returns {Promise}
         */
        _getContent() {
            let _that = this;
            return new Promise((resolve, reject) => {
                _that.$nextTick(() => {
                    let list = _that.$slots.default;
                    if (_that.content && (!list || !list.length)) {
                        let hookIs = _that.$refs.hook_is;
                        resolve(hookIs);
                    } else {
                        resolve(null);
                    }
                });
            });
        },
        /**
         * 获取内容的高度
         */
        _getWrapHeight() {
            let _that = this;
            _that.cHeight = 0;
            _that.$nextTick(() => {
                let hookWrap = _that.$refs.hook_wrap;
                if (hookWrap) {
                    _that.cHeight = hookWrap.clientHeight;
                }
            });
        },
        /**
         * 点击内容区
         * @param {Event} evt 事件对象
         */
        _clickCont(evt) {
            let _that = this;
            if (evt && evt.target === _that.$refs.hookCont) {
                _that._clickBg(evt);
            }
        },
        /**
         * 背景点击事件
         * @param {Event} evt 事件对象
         */
        _clickBg (evt) {
            let _that = this;
            _that.$emit('clickBg', evt);
            switch (_that.maskCloseFlag + '') {
                case '1':
                    _that.closePopup(evt);
                    break;
                case '2':
                    _that.hide();
                    break;
            }
        },
        /**
         * 显示浮窗
         * @param {Boolean} flag 选项
         */
        show (flag) {
            let _that = this;
            _that.myIsShow = _that.isShow;
            _that.showFlag = !flag ? 'show' : false;
            if (_that.showFlag === 'show') { // 显示事件
                let content = _that._getContent();
                content.then((hookIs) => {
                    let $options = hookIs && hookIs.$options;
                    $options && callFn($options.popupShow, [], hookIs);
                });
                _that.$emit(POPUP_EVENT.SHOW, {});
            }
            if (_that.myIsShow) {
                _that._getWrapHeight();
            }
        },
        /**
         * 隐藏浮窗
         * @param {Boolean} flag 选项
         */
        hide (flag) {
            let _that = this;
            _that.myIsShow = false;
            _that.showFlag = !flag ? 'hide' : false;
        },
        /**
         * 带动画的关闭浮窗
         * @param {Event} evt 事件对象
         */
        closePopup (evt) {
            let _that = this;
            _that.transition ? _that.hide() : _that.close(evt);
            _that.showFlag = null;
        },
        /**
         * 关闭浮窗
         * @param {Event} evt 事件对象
         */
        close (evt) {
            let _that = this;
            _that._initEvent = false;
            if (this.isHeight) {
                window.removeEventListener('resize', _that._resize);
                window.removeEventListener('orientationchange', _that._resize);
            }
            if (_that.showFlag === 'hide' && (!evt || evt.type !== 'destroy')) { // 隐藏事件
                let content = _that._getContent();
                content.then((hookIs) => {
                    let $options = hookIs && hookIs.$options;
                    $options && callFn($options.popupHide, [], hookIs);
                });
            } else {
                _that.myIsOpen = false;
                _that.$emit(POPUP_EVENT.CLOSE, evt);
            }

            _that.myIsShow = false;
            _that.$emit(POPUP_EVENT.HIDE, evt);

            _that.showFlag = null;
        }
    }
};
</script>
<style lang="scss">
    @import './_popup.scss';
    @include nuPopup();
    @include nuPopupAnimation();
</style>
