<template>
    <Split v-model="split">
        <template #left>
            <MdEditor ref="editorRef" v-model="editorState.text" :id="editorState.id" :theme="editorState.theme"
                :previewTheme="editorState.previewTheme" :style="{ height: editorState.height }"
                :toolbars="editorState.toolbars" :toolbarsExclude="editorState.toolbarsExclude" @onSave="onSave"
                @onHtmlChanged="getPreviewedHTML">
                <template #defToolbars>
                    <NormalToolbar :title="leftSidebarState == 'open' ? '隐藏文件树' : '显示文件树'" @onClick="toggleLeftSideBar">
                        <template #trigger>
                            <Icon v-if="leftSidebarState == 'open'" type="ios-arrow-dropleft" size="22" />
                            <Icon v-else type="ios-arrow-dropright" size="22" />
                        </template>
                    </NormalToolbar>
                    <NormalToolbar :title="split == 1 ? '显示目录' : '隐藏目录'" @onClick="toggleCatalog">
                        <template #trigger>
                            <Icon :class="split == 1 ? '' : 'md-editor-toolbar-active'" type="ios-list-box-outline"
                                size="22" />
                        </template>
                    </NormalToolbar>
                    <NormalToolbar title="发布文章" @onClick="publish">
                        <template #trigger>
                            <Icon class="md-editor-icon" type="md-cloud-upload" size="22" />
                        </template>
                    </NormalToolbar>
                    <NormalToolbar title="切换编辑器主题" @onClick="toggleEditorTheme">
                        <template #trigger>
                            <Icon v-if="editorState.theme == 'dark'" type="ios-sunny-outline" size="22" />
                            <Icon v-else type="md-moon" size="22" />
                        </template>
                    </NormalToolbar>
                    <DropdownToolbar title="切换预览主题" :visible="editorState.previewThemeListVisible"
                        :onChange="showPreviewThemeList">
                        <template #overlay>
                            <div>
                                <List border size="small">
                                    <ListItem v-for="theme in editorState.previewThemeList" :key="theme"
                                        :class="theme == editorState.previewTheme ? 'md-editor-toolbar-active' : ''"
                                        @click="togglePreviewTheme(theme)">{{ theme }}
                                    </ListItem>
                                </List>
                            </div>
                        </template>
                        <template #trigger>
                            <Icon class="md-editor-icon" type="ios-color-filter-outline" :size="22" />
                        </template>
                    </DropdownToolbar>
                </template>
            </MdEditor>
        </template>
        <template #trigger>
            <div class="split-trigger"></div>
        </template>
        <template #right>
            <div class="split-right md-catalog">
                <MdCatalog :class="hiddenSplitRight" :editorId="editorState.id" :theme="editorState.theme" />
            </div>
        </template>
    </Split>
</template>

<script setup>
import 'md-editor-v3/lib/style.css';
import { MdEditor, MdCatalog, NormalToolbar, DropdownToolbar } from 'md-editor-v3';
import { ref, reactive, watch } from "vue";
import { Message } from 'view-ui-plus'

const props = defineProps({
    markdownCode: {
        type: String,
        required: false,
        default: ''
    },
    leftSidebarState: {
        type: String,
        required: false,
        default: 'open'
    },
    save: {
        type: Function,
        required: false,
        default: (markdownCode) => {
            console.log("save markdown code: " + markdownCode);
        }
    },
});

const emit = defineEmits([
    'update:markdownCode',
    'update:leftSidebarState',
]);

// 定义布局，主要用于在右边显示文章目录
const split = ref(1);
const defaultCatalogSplit = 0.2; // 默认目录和编辑器的比例为 8:2
const hiddenSplitRight = split.value == 1 ? ref('hidden') : ref('');
watch(split, (newSplit) => {
    if (newSplit > 0.95) {
        split.value = 1
        if (hiddenSplitRight.value == '') {
            hiddenSplitRight.value = 'hidden'
        }
    } else {
        if (hiddenSplitRight.value == 'hidden') {
            hiddenSplitRight.value = ''
        }
    }
})

// 加载 Markdown 编辑器
const editorRef = ref(null);
const editorState = reactive({
    id: 'markdown-editor',
    theme: '',
    previewTheme: 'default',
    previewThemeList: ['default', 'github', 'vuepress', 'mk-cute', 'smart-blue', 'cyanosis'],
    previewThemeListVisible: false,
    height: '100vh',
    text: props.markdownCode,
    toolbars: [
        0,
        1,
        '-',
        'bold',
        'underline',
        'italic',
        '-',
        'title',
        'strikeThrough',
        'sub',
        'sup',
        'quote',
        'unorderedList',
        'orderedList',
        'task',
        '-',
        'codeRow',
        'code',
        'link',
        'image',
        'table',
        'mermaid',
        'katex',
        '-',
        'revoke',
        'next',
        'save',
        2,
        '=',
        'prettier',
        'pageFullscreen',
        'fullscreen',
        'preview',
        'previewOnly',
        'htmlPreview',
        'catalog',
        'github',
        3,
        4,
    ],
    toolbarsExclude: ['fullscreen', 'github'], // 工具栏排除全屏和 github 等
});
// 监听 markdownCode（由父组件更新） 和 text（本组件更新）以实现双向更新
watch(() => props.markdownCode, (newCode) => {
    // 当外部传入的 markdownCode 变化时候，更新 text 值
    editorState.text = newCode;
})
watch(() => editorState.text, (newCode) => {
    // 当 text 值变化时，告诉父组件
    emit('update:markdownCode', newCode);
})

const toggleLeftSideBar = () => {
    if (props.leftSidebarState == 'open') {
        emit('update:leftSidebarState', 'close');
    } else {
        emit('update:leftSidebarState', 'open');
    }
}

const toggleCatalog = () => {
    if (split.value < 1) {
        split.value = 1;
    } else {
        split.value = 1 - defaultCatalogSplit;
    }
}

const toggleEditorTheme = () => {
    editorState.theme = editorState.theme == '' ? 'dark' : '';
}

const showPreviewThemeList = (visible) => {
    editorState.previewThemeListVisible = visible;
}

const togglePreviewTheme = (theme) => {
    editorState.previewTheme = theme;
    editorState.previewThemeListVisible = false;
}

const onSave = (v, h) => {
    // 调用 save 方法保存代码（参数 v 为 markdown code）
    props.save(v);

    // 使用 h 可以在保存时直接获取 html
    // h.then((html) => {
    //     console.log(html);
    // });
};

const getPreviewedHTML = (html) => {
    console.log(html);
}

const publish = () => {
    // TODO 调用接口将 markdown 源码或者 HTML 代码发布到云端
    Message.warning('抱歉，该功能暂未开放');
}

// 对父组件暴露数据或方法
defineExpose({})
</script>

<style scoped>
.md-catalog {
    height: 100vh;
    overflow-x: hidden;
    overflow-y: auto;
    scrollbar-width: none;
}
</style>