<template>
    <div v-loading="loading"
         element-loading-text="拼命渲染中"
         element-loading-spinner="el-icon-loading"
         :class="{
            'render-content': true,
            'full-screen': fullScreenStatus,
            'render-error': renderErrorStatus
        }"
         @keyup.esc="contentEscKeyup()">
        <div v-if="renderErrorStatus">
            <div class="el-alert el-alert--error is-light" style="overflow: inherit;">
                <div class="el-alert__content">
                    <span class="el-alert__title is-bold"><i class="el-icon-error"></i> 渲染失败!</span>
                    <div class="el-alert__description">
                        <pre>{{ renderErrorText }}</pre>
                    </div>
                </div>
            </div>
        </div>
        <el-tooltip effect="dark"
                    v-else
                    :content="fullScreenStatus?'退出全屏':'全屏显示'"
                    :open-delay="500"
                    placement="left-start">
            <el-button
                :icon="fullScreenStatus? 'el-icon-copy-document':'el-icon-full-screen'"
                :class="{'tg-btn': true, 'tg-btn-over': toggleButtonMouseover}"
                @click="toggleFullScreen"
                @mouseover.native="mouseoverToggleButton"
                @mouseleave.native="mouseleaveToggleButton"
            ></el-button>
        </el-tooltip>
    </div>
</template>

<script>
import mixin_common from "./js/mixin_common"
import mixin_vue from "./js/mixin_vue"

export default {
    /* 组件用途 */
    $desc_usage: "根据vue配置代码渲染一个实例显示",
    /**
     * 组件可用范围
     * 私有使用【private:张三】
     * 限制使用【protected:二组】
     * 全局使用【public】
     */
    $desc_availableScope: "public",
    /* 组件名称 required */
    name: "cv-vue-render",
    mixins: [
        mixin_common, mixin_vue
    ],
    data() {
        return {
            loading:true,
            toggleButtonMouseover: false,
            fullScreenStatus: false,
        }
    },
    props: {
        height: {
            /* 是否必须 */
            required: false,
            /* 字段释义 */
            $desc_desc: "渲染区域高度",
            /* 是否会被组件内修改取值 */
            $desc_ifWillUpdateInternally: false,
            /* 使用说明 */
            $desc_remark: "如果auto则由组件自动控制，否则由设置的样式控制",
            /* 类型 */
            type: String,
            /* 默认值 */
            default: "auto"
        },
        renderConfig: {
            /* 是否必须 */
            required: true,
            /* 字段释义 */
            $desc_desc: "渲染的配置代码串集合",
            /* 是否会被组件内修改取值 */
            $desc_ifWillUpdateInternally: false,
            /* 使用说明 */
            $desc_remark: "let {template,script,style} = renderConfig;",
            /* 类型 */
            type: Object,
            /* 默认值 */
            default: null
        },
        vueVersion: {
            /* 是否必须 */
            required: false,
            /* 字段释义 */
            $desc_desc: "vue的渲染版本",
            /* 是否会被组件内修改取值 */
            $desc_ifWillUpdateInternally: false,
            /* 使用说明 */
            $desc_remark: "枚举值：2|3",
            /* 类型 */
            type: String,
            /* 默认值 */
            default: "2"
        },
        dependencies: {
            /* 是否必须 */
            required: false,
            /* 字段释义 */
            $desc_desc: "依赖的基础库xml文本",
            /* 是否会被组件内修改取值 */
            $desc_ifWillUpdateInternally: false,
            /* 使用说明 */
            $desc_remark: "为驱动组件示例正常运行所依赖的基础库 - 将解析并追加到运行环境的头部按顺序执行",
            /* 类型 */
            type: String,
            /* 默认值 */
            default: null
        },
    },
    watch: {
        renderConfig: {
            immediate: true,
            handler(newV, oldV) {
                if (!newV) return;
                if (!newV.template) return;
                if (this.vueVersion === '2') {
                    this.callLater();
                }
            }
        },
    },
    mounted() {
        this.setRenderContentHeight(150);
    },
    methods: {
        contentEscKeyup() {
            if (this.renderErrorStatus) return;
            this.fullScreenStatus && this.toggleFullScreen();
        },
        mouseoverToggleButton() {
            this.toggleButtonMouseover = true;
        },
        mouseleaveToggleButton() {
            this.toggleButtonMouseover = false;
        },
        toggleFullScreen() {
            this.fullScreenStatus = !this.fullScreenStatus;
            if (this.fullScreenStatus) {
                document.body.style.overflow = "hidden";
                // DomUtil.fullscreen(this.$el);
            } else {
                delete document.body.style.overflow;
            }
        },
        callLater() {
            let vm = this;
            vm.loading = true;
            function clearCallLater() {
                if (vm.callLaterTimer) {
                    clearTimeout(vm.callLaterTimer);
                    vm.callLaterTimer = null;
                }
            }
            clearCallLater();
            this.callLaterTimer = setTimeout(async function () {
                if (vm.$el) {
                    vm.renderErrorStatus = false;
                    await vm.renderVue2(vm.renderConfig, vm.dependencies);
                    vm.loading = false;
                } else {
                    vm.callLater();
                }
            }, 200)
        }
    }

}
</script>

<style scoped lang="less">
.render-content {
    position: relative;
    box-shadow: 0 2px 10px 0 rgb(0 0 0 / 10%);
}

.render-error {
    overflow: auto;
    pre{
        word-break: break-word;
        white-space: pre-wrap;
    }
}

.full-screen {
    z-index: 99;
    position: fixed;
    background-color: white;
    left: 0;
    top: 0;
    width: 100vw;
    height: 100vh !important;
}

.tg-btn {
    position: absolute;
    right: 0;
    border: 0;
    font-size: 18px;
    background: #ecf5ff;
    padding: 8px;
    opacity: 0.3;
}

.tg-btn-over {
    opacity: 1;
}
</style>
