<template>
    <div v-transfer-dom :data-transfer="true">
        <div :class="className">
            <transition :name="transitions[0]">
                <div v-if="shouldRenderInDom" v-show="open" class="micro-modal-mask" :style="maskStyle"></div>
            </transition>
            <transition :name="transitions[1]">
                <div v-if="shouldRenderInDom" v-show="open" class="micro-modal-content" :style="contentStyle">
                    <!-- 胶囊工具栏 -->
                    <div v-if="capsuleMenuShow" class="micro-modal-cmask"></div>
                    <div class="micro-modal-capsule" :style="capsuleStyle">
                        <div class="micro-modal-capsule-item" @click="onCapsuleMore">
                            <svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
                                <path d="M2 11C3.10457 11 4 10.1046 4 9C4 7.89543 3.10457 7 2 7C0.895431 7 0 7.89543 0 9C0 10.1046 0.895431 11 2 11Z" fill="currentColor"/>
                                <path d="M9 12C10.6569 12 12 10.6569 12 9C12 7.34315 10.6569 6 9 6C7.34315 6 6 7.34315 6 9C6 10.6569 7.34315 12 9 12Z" fill="currentColor"/>
                                <path d="M16 11C17.1046 11 18 10.1046 18 9C18 7.89543 17.1046 7 16 7C14.8954 7 14 7.89543 14 9C14 10.1046 14.8954 11 16 11Z" fill="currentColor"/>
                            </svg>
                        </div>
                        <div class="micro-modal-capsule-line"></div>
                        <div class="micro-modal-capsule-item" @click="onCapsuleClose">
                            <svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
                                <path d="M9 16C12.866 16 16 12.866 16 9C16 5.13401 12.866 2 9 2C5.13401 2 2 5.13401 2 9C2 12.866 5.13401 16 9 16Z" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
                                <path d="M9 12C10.6569 12 12 10.6569 12 9C12 7.34315 10.6569 6 9 6C7.34315 6 6 7.34315 6 9C6 10.6569 7.34315 12 9 12Z" fill="currentColor"/>
                            </svg>
                        </div>
                    </div>

                    <!-- 窗口大小调整 -->
                    <ResizeLine
                        class="micro-modal-resize"
                        v-model="dynamicSize"
                        placement="right"
                        :min="minSize"
                        :max="0"
                        :reverse="true"
                        :beforeResize="beforeResize"
                        @on-change="onChangeResize"/>

                    <!-- 窗口内容 -->
                    <div ref="body" class="micro-modal-body" :style="bodyStyle">
                        <slot></slot>
                    </div>
                </div>
            </transition>
        </div>
    </div>
</template>

<script>
import TransferDom from "../../directives/transfer-dom";
import ResizeLine from "../ResizeLine.vue";
import { mapState } from "vuex";

export default {
    name: 'MicroModal',
    components: {ResizeLine},
    directives: {TransferDom},
    props: {
        open: {
            type: Boolean,
            default: false
        },
        size: {
            type: Number,
            default: 300
        },
        minSize: {
            type: Number,
            default: 300
        },
        options: {
            type: Object,
            default: () => ({})
        },
        beforeClose: Function
    },
    data() {
        return {
            dynamicSize: 0,
            zIndex: 1000,
            capsuleMenuShow: false,
        }
    },
    computed: {
        shouldRenderInDom() {
            return this.open || !!this.options.keep_alive;
        },
        className() {
            return {
                'micro-modal': true,
                'micro-modal-hidden': !this.open,
                'no-dark-content': !this.options.auto_dark_theme,
                'transparent-mode': !!this.options.transparent,
            }
        },
        transitions() {
            if (!!this.options.transparent) {
                return ['', '']
            }
            return ['micro-modal-fade', 'micro-modal-slide']
        },
        bodyStyle() {
            const styleObject = {}
            if (this.options.background) {
                const colors = `${this.options.background}|`.split('|');
                styleObject.background = (this.themeName === 'dark' ? colors[1] : null) || colors[0];
            }
            return styleObject;
        },
        maskStyle({zIndex}) {
            return {zIndex}
        },
        contentStyle({dynamicSize, zIndex}) {
            const width = dynamicSize <= 100 ? `${dynamicSize}%` : `${dynamicSize}px`
            return {width, zIndex}
        },
        capsuleStyle() {
            const styleObject = {
                zIndex: this.zIndex + 1000
            }
            const {capsule} = this.options
            if ($A.isJson(capsule)) {
                if (capsule.visible === false) {
                    styleObject.display = 'none';
                }
                if (typeof capsule.top === 'number') {
                    styleObject.top = `${capsule.top}px`;
                }
                if (typeof capsule.right === 'number') {
                    styleObject.right = `${capsule.right}px`;
                }
            }
            return styleObject
        },
    },
    watch: {
        open: {
            handler(val) {
                if (val) {
                    this.zIndex = typeof window.modalTransferIndex === 'number' ? window.modalTransferIndex++ : 1000;
                }
            },
            immediate: true
        },
        size: {
            handler(val) {
                this.dynamicSize = parseInt(val);
            },
            immediate: true
        }
    },
    methods: {
        beforeResize() {
            return new Promise(resolve => {
                if (this.dynamicSize <= 100) {
                    this.updateSize();
                }
                resolve()
            })
        },

        onChangeResize({event}) {
            if (event === 'up') {
                this.updateSize();
            }
        },

        updateSize() {
            if (this.$refs.body) {
                this.dynamicSize = this.$refs.body.clientWidth;
            }
        },

        onCapsuleMore(event) {
            const customMenu = [];
            const {capsule} = this.options;
            if ($A.isJson(capsule) && $A.isArray(capsule.more_menus)) {
                capsule.more_menus.forEach(item => {
                    if (item.label && item.value) {
                        customMenu.push(item);
                    }
                });
            }
            const systemMenu = [
                {label: this.$L('重启应用'), value: 'restart'},
                {label: this.$L('关闭应用'), value: 'destroy'},
            ];
            if ($A.isMainElectron) {
                systemMenu.unshift({label: this.$L('新窗口打开'), value: 'popout'})
            }
            if (customMenu.length > 0) {
                systemMenu[0].divided = true;
            }
            this.$store.commit('menu/operation', {
                event,
                list: [...customMenu, ...systemMenu],
                size: 'large',
                onVisibleChange: (visible) => {
                    this.capsuleMenuShow = visible;
                },
                onUpdate: (value) => {
                    this.$emit('on-capsule-more', this.options.name, value);
                }
            })
        },

        onCapsuleClose() {
            if (!this.beforeClose) {
                return this.handleClose();
            }
            const before = this.beforeClose(this.options.name);
            if (before && before.then) {
                before.then(() => {
                    this.handleClose();
                });
            } else {
                this.handleClose();
            }
        },

        handleClose() {
            this.$emit('on-confirm-close', this.options.name);
        }
    }
}
</script>

<style lang="scss">
.micro-modal {
    width: 100vw;
    height: 100vh;
    will-change: auto;

    --modal-mask-bg: rgba(0, 0, 0, .4);
    --modal-resize-display: block;
    --modal-content-left: auto;
    --modal-content-min-width: auto;
    --modal-body-margin: 8px;
    --modal-body-border-radius: 16px;
    --modal-body-background-color: #ffffff;
    --modal-dark-filter: none;
    --modal-slide-transform: translate(15%, 0) scale(0.98);

    --modal-capsule-bgcolor: rgba(255, 255, 255, 0.6);
    --modal-capsule-bor-color: rgba(229, 230, 235, 0.6);
    --modal-capsule-hov-bgcolor: rgba(255, 255, 255, 0.9);
    --modal-capsule-hov-shadow: 0 4px 16px rgba(0, 0, 0, 0.12);
    --modal-capsule-line-color: rgba(229, 230, 235, 0.8);

    // 透明模式
    &.transparent-mode {
        --modal-mask-bg: transparent;
        --modal-resize-display: none;
        --modal-content-left: 0;
        --modal-content-min-width: 100%;
        --modal-body-margin: 0;
        --modal-body-border-radius: 0;
        --modal-body-background-color: transparent;
    }

    // 移动端适配（全屏）
    @media (width < 768px) {
        --modal-mask-bg: transparent;
        --modal-resize-display: none;
        --modal-content-left: 0;
        --modal-content-min-width: 100%;
        --modal-body-margin: 0;
        --modal-body-border-radius: 0;
        --modal-slide-transform: translate(0, 15%) scale(0.98);
    }

    &-hidden {
        pointer-events: none;
        animation: fade-hide-zindex 0s forwards;
        animation-delay: 300ms;

        @keyframes fade-hide-zindex {
            to {
                width: 0;
                height: 0;
                overflow: hidden;
                visibility: hidden;
            }
        }
    }

    &-mask {
        filter: var(--modal-dark-filter);
        position: fixed;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;
        background-color: var(--modal-mask-bg);
    }

    &-cmask {
        position: fixed;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;
        z-index: 1;
        background-color: transparent;
    }

    &-capsule {
        filter: var(--modal-dark-filter, none);
        position: absolute;
        top: 10px;
        right: 10px;
        z-index: 2;
        margin-top: var(--modal-body-margin);
        margin-right: var(--modal-body-margin);
        transform: translateY(var(--status-bar-height, 0));
        display: flex;
        align-items: center;
        background: var(--modal-capsule-bgcolor);
        border: 1px solid var(--modal-capsule-bor-color);
        border-radius: 16px;
        transition: box-shadow 0.2s, background 0.2s;

        &:hover {
            background: var(--modal-capsule-hov-bgcolor);
            box-shadow: var(--modal-capsule-hov-shadow);
        }

        &-line {
            width: 1px;
            height: 16px;
            background: var(--modal-capsule-line-color);
        }

        &-item {
            width: 42px;
            height: 30px;
            display: flex;
            align-items: center;
            justify-content: center;
            border-radius: 50%;

            &:hover {
                svg {
                    color: #84C56A;
                }
            }

            svg {
                width: 20px;
                height: 20px;
                color: #303133;
                transition: color 0.2s;
                pointer-events: none;
            }
        }
    }

    &-resize {
        display: var(--modal-resize-display);
        position: absolute;
        top: 0;
        left: var(--modal-body-margin);
        bottom: 0;
        z-index: 1;
        width: 5px;
    }

    &-content {
        position: absolute;
        top: 0;
        right: 0;
        bottom: 0;
        left: var(--modal-content-left);
        display: flex;
        flex-direction: column;
        height: 100%;
        min-width: var(--modal-content-min-width);
        max-width: 100%;
    }

    &-body {
        flex: 1;
        height: 0;
        overflow: hidden;
        margin: var(--modal-body-margin);
        border-radius: var(--modal-body-border-radius);
        background-color: var(--modal-body-background-color);
        position: relative;
    }

    &-fade {
        &-enter-active {
            transition: all .2s ease;
        }

        &-leave-active {
            transition: all .2s ease;
        }

        &-enter,
        &-leave-to {
            opacity: 0;
        }
    }

    &-slide {
        &-enter-active {
            transition: all .2s ease;
        }

        &-leave-active {
            transition: all .2s ease;
        }

        &-enter,
        &-leave-to {
            transform: var(--modal-slide-transform);
            opacity: 0;
        }
    }
}

// 深色模式适配
body.dark-mode-reverse {
    .micro-modal {
        &:not(.transparent-mode) {
            --modal-mask-bg: rgba(230, 230, 230, 0.6);
            --modal-capsule-bgcolor: rgba(210, 210, 210, 0.6);
            --modal-capsule-bor-color: rgba(210, 210, 210, 0.3);
            --modal-capsule-hov-bgcolor: rgba(210, 210, 210, 0.8);
            --modal-capsule-hov-shadow: 0 4px 16px rgba(180, 180, 180, 0.2);
            --modal-capsule-line-color: rgba(180, 180, 180, 0.6);

            &.no-dark-content {
                --modal-dark-filter: invert(100%) hue-rotate(180deg) contrast(100%);
                --modal-body-background-color: #000000;
            }
        }
    }
}
</style>
