<!-- @author huayizhang -->
<!-- @date 2023/02/06-15:47 -->
<!-- @desc yqg-simple-drawer -->

<template>
    <div class="yqg-simple-drawer yqg-drawer-wrapper">
        <a-drawer
            v-for="({
                visible,
                drawerComponent,
                componentProps,
                dialogProps,
                close,
                dismiss,
                afterVisibleChange,
                getContainer
            }, key) in drawerMap"
            :key="key"
            v-bind="{
                visible,
                afterVisibleChange,
                destroyOnClose: true,
                width: 500,
                getContainer,
                ...drawerComponent.dialogProps,
                ...dialogProps
            }"
            @close="dismiss"
        >
            <component
                :is="drawerComponent"
                v-bind="getDrawerComponentProps({
                    drawerComponent,
                    componentProps,
                    close,
                    dismiss
                })"
                v-on="{
                    close,
                    dismiss,
                    ...(componentProps && componentProps.vOn)
                }"
            />
        </a-drawer>
    </div>
</template>

<script type="text/babel">

    import Vue from 'vue';

    import {modal as drawer} from '../mixin';

    let count = 0;

    export default {
        name: 'YqgSimpleDrawer',

        data() {
            return {
                drawerMap: {}
            };
        },

        beforeCreate() {
            this.$nextTick(() => {
                if (count > 1) throw new Error('YqgSimpleDrawer is singleton pattern!');
            });

            count += 1;
        },

        created() {
            const {open, clearDrawers, closeDrawers, $router} = this;
            Vue.prototype.$drawer = {
                open,
                clearDrawers,
                closeDrawers
            };
            $router.beforeEach((from, to, next) => {
                clearDrawers();
                next();
            });
        },

        beforeDestroy() {
            count -= 1;
        },

        methods: {
            open(drawerComponent, componentProps, options) {
                const {drawerMap, closeDrawer, clearDrawer} = this;
                const {dialogProps, getContainer} = options || {};

                return new Promise((resolve, reject) => {
                    const key = `${drawerComponent.name}-${Object.keys(drawerMap).length}`;
                    const close = (...args) => {
                        closeDrawer(key);
                        resolve(...args);
                    };

                    const dismiss = (...args) => {
                        closeDrawer(key);
                        reject(...args);
                    };

                    const afterVisibleChange = visible => {
                        // 关闭动画完成后销毁
                        if (!visible) clearDrawer(key);
                    };

                    // 先渲染，再显示，这样可以保证开启动画能够正常显示
                    this.$set(this.drawerMap, key, {
                        key,
                        drawerComponent,
                        componentProps,
                        dialogProps,
                        close,
                        dismiss,
                        afterVisibleChange,
                        getContainer
                    });
                    this.$nextTick(() => this.$set(this.drawerMap[key], 'visible', true));
                });
            },

            getDrawerComponentProps({drawerComponent, componentProps, close, dismiss}) {
                const {vOn, ...restProps} = componentProps ?? {}; // eslint-disable-line @typescript-eslint/no-unused-vars
                if (drawerComponent.mixins?.includes(drawer) || drawerComponent.functional) {
                    return {
                        ...restProps,
                        close,
                        dismiss
                    };
                }

                Object.entries({close, dismiss}).forEach(([propName, func]) => {
                    if (drawerComponent.props?.[propName]) {
                        restProps[propName] = func;
                    }
                });

                return restProps;
            },
            // 关闭不销毁，走动画流程
            closeDrawer(key) {
                const {drawerMap} = this;
                if (drawerMap[key]) {
                    this.$set(drawerMap, key, {
                        ...drawerMap[key],
                        visible: false
                    });
                }
            },

            closeDrawers() {
                const {drawerMap} = this;
                Object.keys(drawerMap ?? {}).forEach(this.closeDrawer);
            },
            // 直接销毁，不走动画流程
            clearDrawer(key) {
                this.$delete(this.drawerMap, key);
            },

            clearDrawers() {
                this.drawerMap = {};
            }
        }
    };
</script>
