<template>
    <Split v-model="split" min="5px">
        <template #left>
            <div class="split-left" :class="hiddenSplitLeft">
                <LeftSidebar v-model:rootFolderPath="rootFolderPath" v-model:currentFilePath="currentFilePath"
                    :confirmSwitchingFile="confirmSwitchingFile">
                </LeftSidebar>
            </div>
        </template>
        <template #trigger>
            <div ref="splitTrigger" class="split-trigger"></div>
        </template>
        <template #right>
            <div ref="splitRight" class="split-right">
                <MainEditor ref="mainEditor" v-model:markdownCode="markdownCode"
                    v-model:leftSidebarState="leftSidebarState" :save="writeFileContent" @exportPDF="exportMarkdownPDF">
                </MainEditor>
            </div>
        </template>
    </Split>
</template>

<script setup>
import LeftSidebar from './components/LeftSidebar.vue'
import MainEditor from './components/MainEditor.vue'
import { ref, watch, useTemplateRef, nextTick, onMounted, onUnmounted } from "vue";
import { invoke } from "@tauri-apps/api/core";
import { getCurrentWindow } from "@tauri-apps/api/window";
import { readTextFile, writeTextFile, writeFile, exists } from '@tauri-apps/plugin-fs';
import { save, confirm } from '@tauri-apps/plugin-dialog';
import { Message, Notice, Modal } from 'view-ui-plus'
import { GetSingleArticle, UpdateArticle } from '/src/utils/userHandler';

// 原始示例数据，仅供参考
const greetMsg = ref("");
const name = ref("");
async function greet() {
    // Learn more about Tauri commands at https://tauri.app/develop/calling-rust/
    greetMsg.value = await invoke("greet", { name: name.value });
}

// 使用 Split 组件动态控制页面左右布局
const defaultSplit = 0.15; // 默认左侧边栏和右侧区域的比例为 1.5:8.5
const initSplit = localStorage.getItem('splitValueOfFolderTree');
const split = initSplit === null ? ref(defaultSplit) : ref(Number(initSplit));
const splitTrigger = useTemplateRef('splitTrigger');
const splitRight = useTemplateRef('splitRight');
const splitRightWidth = ref(0);
const hiddenSplitLeft = ref('');
const leftSidebarState = split.value > 0 ? ref('open') : ref('close');
watch(split, (newSplit) => {
    localStorage.setItem('splitValueOfFolderTree', newSplit);
    splitRightWidth.value = splitRight.value.offsetWidth;
    // 当 split 小于某个值时，隐藏左边布局
    if (newSplit < 0.05) {
        split.value = 0;
        leftSidebarState.value = 'close';
        if (hiddenSplitLeft.value == '') {
            hiddenSplitLeft.value = 'hidden';
        }
    } else {
        leftSidebarState.value = 'open';
        if (hiddenSplitLeft.value == 'hidden') {
            hiddenSplitLeft.value = '';
        }
    }
})
watch(leftSidebarState, (state) => {
    if (state == 'open') {
        split.value = defaultSplit;
    } else {
        split.value = 0;
    }
})

// 监听根目录路径。如果之前已经选过目录，初始界面直接加载该目录
const rootFolderPath = ref(localStorage.getItem('rootPathOfFolderTree') || "");
watch(rootFolderPath, (newRootPath) => {
    localStorage.setItem('rootPathOfFolderTree', newRootPath);
})

// <FolderTree> 完成文件树渲染后，点击文件得到 currentFilePath
const currentFilePath = ref(localStorage.getItem('currentSelectedFilePath') || "");
let switchFilePath = true; // 切换文件时，避免触发 markdownCode 的 watch 事件
// 读取 currentFilePath 的文件内容，填充到 MarkdownEditor 之中
watch(currentFilePath, async (newFilePath) => {
    switchFilePath = true;
    localStorage.setItem('currentSelectedFilePath', newFilePath);
    await readFileContent(newFilePath);
})
// 切换文件时，如果当前文件的变动未保存，允许用户取消切换动作，保存当前文件内容
const confirmSwitchingFile = () => {
    return new Promise((resolve) => {
        // 如果当前文件内容未被修改，允许切换文件
        if (currentFileSaved()) {
            resolve(true);
            return;
        }
        // 如果当前文件内容被修改，允许用户取消切换，可以保存后再切换
        Modal.confirm({
            title: '当前文件的内容变动未保存',
            content: `<p><b>${currentFilePath.value}</b> 内容被修改但仍未保存，确认切换文件？<br/><br/>注：确认切换之后，内容变动会丢失</p>`,
            okText: "仍然切换",
            cancelText: "取消切换",
            onOk: () => {
                resolve(true);
            },
            onCancel: () => {
                resolve(false);
            }
        });
    });
}
const currentFileSaved = () => {
    // 判断当前文件内容是否被修改但未保存，如果已保存则返回 true
    const lastSaveTimeValue = lastSaveTime.get(currentFilePath.value);
    const isUpdated = lastSaveTimeValue && lastUpdateTime.value > lastSaveTimeValue;
    return !isUpdated;
}
const getFileNameFromFilePath = (filePath) => {
    const fullFileName = filePath.split('/').pop();
    const splitResult = fullFileName.split(".");
    splitResult.pop(); // 丢掉后缀
    return splitResult.join('.');
}

const mainEditor = ref(null);
const markdownCode = ref("# Hello Markdown");
const lastSaveTime = new Map(); // 记录每个文件的最后保存时间
const lastUpdateTime = ref(0); // 记录当前文件的最后更新时间
watch(markdownCode, (newMarkdownCode) => {
    if (switchFilePath === true) {
        switchFilePath = false;
        return;
    }
    lastUpdateTime.value = new Date().getTime();
    console.log("code be updated");
})
async function readFileContent(filePath) {
    if (window.__TAURI_INTERNALS__ === undefined) {
        // 调用接口读取 currentFilePath 文件内容
        const match = filePath.match(/(\d+)$/);
        const articleID = match ? parseInt(match[1], 10) : null;
        GetSingleArticle(articleID).then((data) => {
            markdownCode.value = data.mdCode;
            currentFilePath.value = filePath;
            lastSaveTime.set(filePath, new Date().getTime());
            Message.success('已读取文件内容，并加载到编辑器中:' + filePath);
        }).catch((error) => {
            Message.error(`调用异常: ${error}`);
        });
        return;
    }
    try {
        const fileContent = await readTextFile(filePath);
        markdownCode.value = fileContent;
        currentFilePath.value = filePath;
        lastSaveTime.set(filePath, new Date().getTime());
        Message.success('已读取文件内容，并加载到编辑器中:' + filePath);
    } catch (err) {
        Message.error('文件读取失败:' + err);
    }
}
async function writeFileContent(markdownCode) {
    // 如果未选择任何文件，则不触发写文件事件
    if (currentFilePath.value.length == 0) {
        Message.warning('当前编辑器暂未关联目标文件，请在左侧打开目录并选择一个文件')
        return;
    }
    try {
        if (window.__TAURI_INTERNALS__ === undefined) {
            // 调用接口更新 currentFilePath 文件内容
            const match = currentFilePath.value.match(/(\d+)$/);
            const articleID = match ? parseInt(match[1], 10) : null;
            UpdateArticle(articleID, null, markdownCode).then((data) => {
                Message.success('更新成功');
            }).catch((error) => {
                Message.error(`更新异常: ${error}`);
            });
        } else {
            const exist = await exists(currentFilePath.value);
            if (!exist) {
                throw new Error(currentFilePath.value + " 文件不存在.");
            }
            await writeTextFile(currentFilePath.value, markdownCode);
            Message.success('文件更新成功:' + currentFilePath.value);
        }
        lastSaveTime.set(currentFilePath.value, new Date().getTime());
    } catch (err) {
        Message.error('文件更新失败:' + err);
    }
}
async function exportMarkdownPDF(pdfBuffer) {
    let fileName = 'markdown.pdf';
    if (currentFilePath.value.length > 0) {
        fileName = getFileNameFromFilePath(currentFilePath.value) + '.pdf';
    }

    try {
        const filePath = await save({
            title: '保存 PDF',      // 对话框标题
            defaultPath: fileName, // 保存的文件名称
        });

        if (filePath) {
            await writeFile(filePath, new Uint8Array(pdfBuffer));
            Notice.success({
                title: '导出成功',
                desc: 'PDF 已保存至 ' + filePath,
            });
        } else {
            console.log('用户主动取消');
        }
    } catch (err) {
        console.log(err);
        Notice.error({
            title: '导出失败',
            desc: '请将文件保存在用户有权限的目录之下',
        });
    }
}

const resizeHandler = () => {
    // splitRight 的宽度为视口宽度右边百分比，再减去 splitTrigger 的宽度
    splitRightWidth.value = window.innerWidth * (1 - split.value) - splitTrigger.value.offsetWidth;
}
onMounted(async () => {
    // 使用 nextTick 确保页面组件已完成挂载和渲染
    await nextTick();
    resizeHandler();
    // 监听页面宽度和高度，调整 markdown 编辑器的高宽度
    window.addEventListener('resize', resizeHandler);
    // 打开上一次选择的文件的内容
    if (currentFilePath.value.length > 0) {
        await readFileContent(currentFilePath.value);
    }

    // 监听窗口关闭事件。如果当前文件内容未保存，允许取消关闭事件
    await getCurrentWindow().onCloseRequested(async (event) => {
        if (currentFileSaved()) {
            return; // 如果当前文件已保存，允许关闭窗口
        }
        const confirmed = await confirm('当前文件内容未保存，是否确认关闭窗口？');
        if (!confirmed) {
            // user did not confirm closing the window; let's prevent it
            event.preventDefault();
        }
    });
});
onUnmounted(() => {
    window.removeEventListener('resize', resizeHandler);
});
</script>

<style>
body {
    overflow: hidden;
    /* 禁用所有方向滚动 */
}

.split-left {
    height: 100vh;
    border-right: 1px solid #dcdee2;
    overflow-x: hidden;
    overflow-y: auto;
    scrollbar-width: none;
}

.split-trigger {
    width: 2px;
    height: 100vh;
    background-color: #e6e6e6;
}

.split-trigger:hover {
    cursor: ew-resize;
}

.split-right {
    margin-left: 2px;
}

.hidden {
    display: none;
}
</style>
