<template>
    <div v-if="MdVueComp" style="position: relative">
        <component :is="MdVueComp" :style="mdContentStyle"></component>
        <outline @widthChange="outlineWidthChange" v-if="outline"></outline>
    </div>
</template>

<script>

import Outline from "./component/outline/index";
import mdTools from "./js/md-tools"
// import DomUtil from "../../util/DomUtil"

export default {
    components: {Outline},
    /* 组件用途 */
    $desc_usage: "基础业务展示用户列表",
    /**
     * 组件可用范围
     * 私有使用【private:张三】
     * 限制使用【protected:二组】
     * 全局使用【public】
     */
    $desc_availableScope: "public",
    /* 组件名称 required */
    name: "cv-md-render",

    props: {
        content: {
            /* 是否必须 */
            required: true,
            /* 字段释义 */
            $desc_desc: "MD文本源码",
            /* 是否会被组件内修改取值 */
            $desc_ifWillUpdateInternally: false,
            /* 使用说明 */
            $desc_remark: "外部传入md源码，组件自动解析功能及样式",
            /* 类型 */
            type: String,
            /* 默认值 */
            default: null
        },
        outline: {
            /* 是否必须 */
            required: false,
            /* 字段释义 */
            $desc_desc: "是否显示解析大纲",
            /* 是否会被组件内修改取值 */
            $desc_ifWillUpdateInternally: false,
            /* 使用说明 */
            $desc_remark: "当md描述信息比较多的情况下，可根据层级显示对应的大纲结构",
            /* 类型 */
            type: Boolean,
            /* 默认值 */
            default: false
        },
        demoRenderType: {
            /* 是否必须 */
            required: false,
            /* 字段释义 */
            $desc_desc: "示例渲染类型",
            /* 是否会被组件内修改取值 */
            $desc_ifWillUpdateInternally: false,
            /* 使用说明 */
            $desc_remark: "枚举：iframe|div 如果是iframe则开辟新作用域注入js渲染",
            /* 类型 */
            type: String,
            /* 默认值 */
            default: "div"
        },
        demoVueVersion: {
            /* 是否必须 */
            required: false,
            /* 字段释义 */
            $desc_desc: "示例的vue渲染版本",
            /* 是否会被组件内修改取值 */
            $desc_ifWillUpdateInternally: false,
            /* 使用说明 */
            $desc_remark: "枚举值：2|3,如果为div渲染模式，是否渲染成功取决于当前项目环境",
            /* 类型 */
            type: String,
            /* 默认值 */
            default: "2"
        },
        getDependencies: {
            /* 是否必须 */
            required: false,
            /* 字段释义 */
            $desc_desc: "解析依赖xml的回调，返回为驱动组件示例正常运行所依赖的基础库XML",
            /* 是否会被组件内修改取值 */
            $desc_ifWillUpdateInternally: false,
            /* 使用说明 */
            $desc_remark: "为驱动组件示例正常运行所依赖的基础库 - 将解析并追加到运行环境的头部按顺序执行 demoRenderType为iframe时生效",
            /* 类型 */
            type: Function,
            /* 默认值 */
            default: (dependencies) => {
                return dependencies
            }
        },
        components: {
            /* 是否必须 */
            required: false,
            /* 字段释义 */
            $desc_desc: "渲染示例所需的外部引用组件",
            /* 是否会被组件内修改取值 */
            $desc_ifWillUpdateInternally: false,
            /* 使用说明 */
            $desc_remark: "渲染示例所需的外部引用组件  demoRenderType为div时生效",
            /* 类型 */
            type: Object,
            /* 默认值 */
            default: () => {
                return {}
            }
        },
    },
    /* 组件派发的事件 */
    $desc_events: [
        {
            /* 在线运行demo示例 */
            name: "on-line-run-demo",
            /* 回调参数 */
            callBackParam: {
                /* 回调参数名称 */
                name: "config",
                /* 回调参数类型 */
                type: Object,
                /* 回调参数描述 */
                desc: "let {renderConfig,dependencies,vueVersion} = config;",
            },
            /* 描述 */
            desc: "点击示例区域交互的在线运行,触发事件",
        }
    ],
    /* 是否支持全局事件 */
    $desc_ifSupportGlobalEventBus: false,
    data() {
        return {
            MdVueComp: null,
            mdContentStyle:{},
        }
    },
    mounted() {
        this.loadMdVueComp();
    },
    beforeDestroy() {
        this.notification && this.notification.close();
    },
    methods: {
        async loadMdVueComp() {
            let vm = this;
            let content = this.content.trim();
            let MdVueComp = content ? await mdTools.analysis2vue({
                content: content,
                async getDependencies(dependencies) {
                    return vm.getDependencies(dependencies)
                },
                renderType: this.demoRenderType,
                vueVersion: this.demoVueVersion,
                components: this.components,
                onLineRun: this.onLineRun.bind(this)
            }) : null;
            // vm.$nextTick(() => {
            //     vm.initOutline();
            // })
            this.MdVueComp = MdVueComp;
        },
        /**
         * 在线运行demo
         */
        onLineRun(data) {
            this.$emit("on-line-run-demo", data)
        },
        /**
         * 销毁大纲视图
         */
        destroyOutline() {
            this.notification && this.notification.close();
            this.notification = null;
        },
        /**
         * 初始化大纲视图
         */
        initOutline() {
            this.destroyOutline();
            if (!this.outline) return;
            if (!this.outline) return;
            if (!this.$el.getElementsByClassName) {
                this.$nextTick(() => {
                    this.initOutline();
                })
                return;
            }
            let elementDoc = this.$el.getElementsByClassName("element-doc");
            if (!elementDoc.length) return;
            elementDoc = elementDoc[0];
            let id = app.VM.getInstance().$route.hash.replace("#", "");
            let ele = document.getElementById(id);
            ele && DomUtil.scrollToElement(ele, 30, 200);
            let arr = [];
            $(elementDoc).find(".header-anchor").parent().each(function (index, ele) {
                let item = {
                    level: ele.tagName.replace("H", ""),
                    text: ele.innerText.replace("¶", "").trim(),
                    id: ele.id
                };
                if (!arr.length) {
                    arr.push(item);
                    return;
                }
                let lastItem = arr[arr.length - 1];
                if (lastItem.level == item.level) {
                    arr.push(item);
                } else if (lastItem.level < item.level) {
                    let pItem = lastItem;
                    while (true) {
                        let children = pItem.children = pItem.children || [];
                        if (!children.length || children[0].level >= item.level) {
                            children.push(item);
                            return;
                        } else {
                            pItem = children[children.length - 1];
                        }
                    }
                }
            })
            let html = `<div class="out-line">${(function () {
                function getHtml(arr) {
                    let str = "";
                    arr.forEach(function (ite) {
                        str += `<li><a href="#${ite.id}">${ite.text}</a>${getHtml(ite.children || [])}</li>`
                    })
                    return str ? `<ul>${str}</ul>` : "";
                }

                return getHtml(arr);
            })()}</div>`;
            let title = $(elementDoc).find("h1:eq(0)").text() || "";
            title && (title += '-')
            this.notification = app.VM.getInstance().$notify({
                title: title + '大纲',
                duration: 0,
                dangerouslyUseHTMLString: true,
                message: html
            });
        },
        outlineWidthChange(width){
            this.mdContentStyle = {
                "margin-right": width +"px",
            }
        }
    }


}
</script>

<style lang="less" src="./css/index.less">

</style>
