<?php

if (!defined('__TYPECHO_ROOT_DIR__')) exit;

class Mirai_Editor {

    public static function getEditorType() {
        try {
            $options = \Typecho\Widget::widget('Widget\Options');
        } catch (Exception $e) {
            $options = \Widget\Options::alloc();
        }
        $type = isset($options->miraiEditorType) ? $options->miraiEditorType : 'default';
        return Mirai_featureEnabled('editor') ? $type : 'default';
    }

    public static function renderEditorMd($content) {
        try {
            $options = \Typecho\Widget::widget('Widget\Options');
        } catch (Exception $e) {
            $options = \Widget\Options::alloc();
        }
        $themeUrl = Mirai_getThemeUrl();
        $editorConfig = self::getEditorConfig();
        $cloudTypesJs = json_encode(Mirai_cloudTypesForJs(), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
        $cloudSvgBase = json_encode(Mirai_cloudAssetUrl(), JSON_UNESCAPED_SLASHES);

        ?>
        <link rel="stylesheet" href="<?php echo $themeUrl; ?>/common/lib/editor.md/css/editormd.min.css" />
        <link rel="stylesheet" href="<?php echo $themeUrl; ?>/assets/editor/editor.css" />
        <style>
            .editormd-fullscreen { z-index: 99999; }
            .editormd { margin-bottom: 15px; }
            #text { display: none; }
            .typecho-post-area > .col-mb-9 .typecho-label { display: none; }
        </style>

        <script src="<?php echo $themeUrl; ?>/common/lib/editor.md/editormd.min.js"></script>
        <script src="<?php echo $themeUrl; ?>/assets/editor/editor.js"></script>

        <script>
        (function() {
            var miraiEditor;
            var editorConfig = <?php echo json_encode($editorConfig); ?>;
            var cloudTypes = <?php echo $cloudTypesJs; ?>;
            var cloudSvgBase = <?php echo $cloudSvgBase; ?>;

            $(document).ready(function() {
                var originalTextarea = $('#text');
                if (originalTextarea.length === 0) return;

                var editorContainer = $('<div id="mirai-editormd"></div>');
                originalTextarea.after(editorContainer);
                editorContainer.append(originalTextarea);

                miraiEditor = editormd("mirai-editormd", {
                    width: "100%",
                    height: editorConfig.height || 745,
                    path: "<?php echo $themeUrl; ?>/common/lib/editor.md/lib/",
                    theme: editorConfig.theme || "default",
                    previewTheme: editorConfig.previewTheme || "default",
                    editorTheme: editorConfig.editorTheme || "default",
                    markdown: $("#text").val(),
                    watch: true,
                    lineNumbers: false,
                    codeFold: false,
                    saveHTMLToTextarea: false,
                    searchReplace: false,
                    htmlDecode: true,
                    taskList: true,
                    tocm: false,
                    tex: false,
                    flowChart: false,
                    sequenceDiagram: false,
                    autoFocus: false,
                    imageUpload: true,
                    imageFormats: ["jpg", "jpeg", "gif", "png", "avif", "webp"],
                    imageUploadURL: "<?php echo \Widget\Security::alloc()->getTokenUrl(\Typecho\Common::url('/action/upload', $options->index)); ?>",
                    syncScrolling: "single",
                    toolbarIcons: function() {
                        return [
                            "bold", "del", "italic", "quote", "|",
                            "h1", "h2", "h3", "|",
                            "list-ul", "list-ol", "hr", "|",
                            "link", "image", "code", "code-block", "table", "|",
                            "textAlign", "insertMedia", "insertShortcode", "insertCloud", "|",
                            "search", "watch", "preview", "fullscreen", "help"
                        ];
                    },
                    toolbarIconsClass: {
                        textAlign: "fa-align-justify",
                        insertMedia: "fa-play-circle-o",
                        insertShortcode: "fa-terminal",
                        insertCloud: "fa-cloud-download"
                    },
                    lang: {
                        toolbar: {
                            textAlign: "文本对齐",
                            insertMedia: "插入音视频",
                            insertShortcode: "插入短代码",
                            insertCloud: "网盘下载"
                        }
                    },
                    toolbarHandlers: {
                        textAlign: function(cm) {
                            MiraiEditor.toggleAlignMenu(MiraiEditor.createCmAdapter(cm), '.editormd-toolbar a[title="文本对齐"]');
                        },
                        insertMedia: function(cm) {
                            MiraiEditor.toggleMediaMenu(MiraiEditor.createCmAdapter(cm), '.editormd-toolbar a[title="插入音视频"]');
                        },
                        insertShortcode: function(cm) {
                            MiraiEditor.toggleHideMenu(MiraiEditor.createCmAdapter(cm), '.editormd-toolbar a[title="插入短代码"]');
                        },
                        insertCloud: function(cm) {
                            MiraiEditor.insertCloudModal(MiraiEditor.createCmAdapter(cm), cloudSvgBase, cloudTypes);
                        }
                    },
                    onload: function() {
                        $('label[for="text"]').hide();
                    },
                    onchange: function() {
                        $("#text").val(this.getMarkdown());
                    }
                });

                $('form[name="write_post"], form[name="write_page"]').on('submit', function() {
                    if (miraiEditor) {
                        $("#text").val(miraiEditor.getMarkdown());
                    }
                });

                if (typeof Typecho !== 'undefined') {
                    Typecho.insertFileToEditor = function(file, url, isImage) {
                        if (miraiEditor) {
                            var value;
                            if (isImage) {
                                value = '![' + file + '](' + url + ')';
                            } else {
                                value = '[' + file + '](' + url + ')';
                            }
                            miraiEditor.insertValue(value);
                        }
                    };

                    Typecho.uploadComplete = function(attachment) {
                        Typecho.insertFileToEditor(attachment.title, attachment.url, attachment.isImage);
                    };
                }
            });
        })();
        </script>
        <?php
    }

    private static function getEditorConfig() {
        try {
            $options = \Typecho\Widget::widget('Widget\Options');
        } catch (Exception $e) {
            $options = \Widget\Options::alloc();
        }

        return [
            'height' => isset($options->miraiEditorHeight) ? intval($options->miraiEditorHeight) : 745,
            'theme' => isset($options->miraiEditorTheme) ? $options->miraiEditorTheme : 'default',
            'previewTheme' => isset($options->miraiEditorPreviewTheme) ? $options->miraiEditorPreviewTheme : 'default',
            'editorTheme' => isset($options->miraiEditorEditorTheme) ? $options->miraiEditorEditorTheme : 'default',
        ];
    }

    public static function renderVditor($content) {
        try {
            $options = \Typecho\Widget::widget('Widget\Options');
        } catch (Exception $e) {
            $options = \Widget\Options::alloc();
        }
        $themeUrl = Mirai_getThemeUrl();
        $editorConfig = self::getEditorConfig();
        $uploadUrl = \Widget\Security::alloc()->getTokenUrl(
            \Typecho\Common::url('/action/upload', $options->index)
        );
        $vditorTheme = ($editorConfig['theme'] === 'dark') ? 'dark' : 'classic';
        $vditorContentTheme = ($editorConfig['previewTheme'] === 'dark') ? 'dark' : 'light';
        $vditorCodeTheme = 'github';
        if ($editorConfig['editorTheme'] === 'monokai') {
            $vditorCodeTheme = 'monokai';
        } elseif ($editorConfig['editorTheme'] === 'ambiance') {
            $vditorCodeTheme = 'dracula';
        } elseif ($editorConfig['editorTheme'] !== 'default') {
            $vditorCodeTheme = 'github';
        }
        $cloudTypesJs = json_encode(Mirai_cloudTypesForJs(), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
        $cloudSvgBase = json_encode(Mirai_cloudAssetUrl(), JSON_UNESCAPED_SLASHES);

        ?>
        <link rel="stylesheet" href="<?php echo $themeUrl; ?>/common/lib/vditor/3.11.2/dist/index.min.css" />
        <link rel="stylesheet" href="<?php echo $themeUrl; ?>/assets/editor/editor.css" />
        <style>
            #text { display: none; }
            .typecho-post-area > .col-mb-9 .typecho-label { display: none; }
            #mirai-vditor { margin-bottom: 15px; }
            #mirai-vditor .vditor-toolbar { flex-wrap: wrap; }
            .vditor--fullscreen { z-index: 99999; }
        </style>

        <script src="<?php echo $themeUrl; ?>/common/lib/vditor/3.11.2/dist/index.min.js"></script>
        <script src="<?php echo $themeUrl; ?>/assets/editor/editor.js"></script>

        <script>
        (function() {
            var miraiVditor;
            var editorConfig = <?php echo json_encode($editorConfig); ?>;
            var uploadUrl = <?php echo json_encode($uploadUrl); ?>;
            var vditorTheme = <?php echo json_encode($vditorTheme); ?>;
            var vditorContentTheme = <?php echo json_encode($vditorContentTheme); ?>;
            var vditorCodeTheme = <?php echo json_encode($vditorCodeTheme); ?>;
            var vditorCDN = '<?php echo $themeUrl; ?>/common/lib/vditor/3.11.2';
            var cloudTypes = <?php echo $cloudTypesJs; ?>;
            var cloudSvgBase = <?php echo $cloudSvgBase; ?>;

            $(document).ready(function() {
                var originalTextarea = $('#text');
                if (originalTextarea.length === 0) return;

                var editorContainer = $('<div id="mirai-vditor"></div>');
                originalTextarea.after(editorContainer);

                var cidInput = $('input[name=cid]');

                miraiVditor = new Vditor('mirai-vditor', {
                    cdn: vditorCDN,
                    height: editorConfig.height || 745,
                    mode: 'wysiwyg',
                    theme: vditorTheme,
                    icon: 'ant',
                    lang: 'zh_CN',
                    value: originalTextarea.val() || '',
                    placeholder: '开始撰写内容...',
                    typewriterMode: false,
                    cache: { enable: false },
                    counter: { enable: true, type: 'text' },
                    toolbarConfig: { pin: true },
                    customWysiwygToolbar: function() {},
                    resize: { enable: true, position: 'bottom' },
                    outline: { enable: false, position: 'left' },
                    _lutePath: '',
                    preview: {
                        theme: { current: vditorContentTheme, path: vditorCDN + '/dist/css/content-theme' },
                        hljs: { enable: false },
                        markdown: { toc: true, mark: true, autoSpace: true, footnotes: true, html: true },
                        math: { engine: 'KaTeX' },
                        actions: [
                            { key: 'desktop', text: '桌面端' },
                            { key: 'tablet', text: '平板端' },
                            { key: 'mobile', text: '移动端' },
                            { key: 'mp-wechat', text: '微信公众号' },
                            { key: 'zhihu', text: '知乎' }
                        ]
                    },
                    toolbar: [
                        'emoji', 'headings', 'bold', 'italic', 'strike', 'link', '|',
                        'list', 'ordered-list', 'check', 'outdent', 'indent', '|',
                        'quote', 'line', 'code', 'inline-code', 'insert-before', 'insert-after', '|',
                        'upload', 'table', '|',
                        {
                            name: 'textAlign',
                            tip: '文本对齐',
                            icon: '<svg viewBox="0 0 32 32" width="14" height="14"><path d="M2 6h28v2H2zm0 6h18v2H2zm0 6h28v2H2zm0 6h18v2H2z" fill="currentColor"/></svg>',
                            click: function() { MiraiEditor.toggleAlignMenu(MiraiEditor.createVditorAdapter(miraiVditor), '.vditor-toolbar [data-type="textAlign"]'); }
                        },
                        {
                            name: 'insertMedia',
                            tip: '插入音视频',
                            icon: '<svg viewBox="0 0 32 32" width="14" height="14"><path d="M25.263 15.159l-17.308-14.927c-0.645-0.555-1.591-0.055-1.591 0.841v29.853c0 0.895 0.945 1.395 1.591 0.841l17.308-14.927c0.495-0.427 0.495-1.255 0-1.682z" fill="currentColor"></path></svg>',
                            click: function() { MiraiEditor.toggleMediaMenu(MiraiEditor.createVditorAdapter(miraiVditor), '.vditor-toolbar [data-type="insertMedia"]'); }
                        },
                        {
                            name: 'insertShortcode',
                            tip: '插入短代码',
                            icon: '<svg viewBox="0 0 32 32" width="14" height="14"><path d="M14.545 4.364h2.909v23.273h-2.909zM4.364 9.455h2.909v13.091h-2.909zM24.727 9.455h2.909v13.091h-2.909z" fill="currentColor"/></svg>',
                            click: function() { MiraiEditor.toggleHideMenu(MiraiEditor.createVditorAdapter(miraiVditor), '.vditor-toolbar [data-type="insertShortcode"]'); }
                        },
                        {
                            name: 'insertCloud',
                            tip: '网盘下载',
                            icon: '<svg viewBox="0 0 24 24" width="16" height="16"><path d="M19.35 10.04A7.49 7.49 0 0 0 12 4C9.11 4 6.6 5.64 5.35 8.04A5.994 5.994 0 0 0 0 14c0 3.31 2.69 6 6 6h13c2.76 0 5-2.24 5-5 0-2.64-2.05-4.78-4.65-4.96zM17 13l-5 5-5-5h3V9h4v4h3z" fill="currentColor"/></svg>',
                            click: function() { MiraiEditor.insertCloudModal(MiraiEditor.createVditorAdapter(miraiVditor), cloudSvgBase, cloudTypes); }
                        },
                        '|',
                        'undo', 'redo', '|',
                        'edit-mode', 'both', 'preview', 'fullscreen', '|',
                        'outline', 'export', 'help'
                    ],
                    upload: {
                        url: uploadUrl,
                        fieldName: 'file',
                        max: 10 * 1024 * 1024,
                        multiple: false,
                        accept: 'image/*, .zip, .rar, .7z, .pdf, .doc, .docx, .xls, .xlsx, .ppt, .pptx',
                        linkToImgUrl: <?php echo json_encode(\Typecho\Common::url('/action/mirai_api?api=upload_link_img&token=' . \Widget\Security::alloc()->getToken('api'), $options->index), JSON_UNESCAPED_SLASHES); ?>,
                        handler: function(files) {
                            if (!files || files.length === 0) return null;
                            for (var i = 0; i < files.length; i++) {
                                uploadFileToTypecho(files[i]);
                            }
                            return null;
                        }
                    },
                    hint: {
                        extend: [{
                            key: '@',
                            hint: function(value) {
                                var keyword = value.substring(1);
                                return new Promise(function(resolve) {
                                    if (!keyword) {
                                        resolve([]);
                                        return;
                                    }
                                    var formData = new FormData();
                                    formData.append('_ajax', '1');
                                    formData.append('keyword', keyword);
                                    fetch(<?php echo json_encode(\Typecho\Common::url('/action/mirai_api?api=search_users', $options->index), JSON_UNESCAPED_SLASHES); ?>, {
                                        method: 'POST',
                                        body: formData
                                    })
                                    .then(function(r) { return r.json(); })
                                    .then(function(data) {
                                        if (data && data.success && data.users) {
                                            resolve(data.users.map(function(u) {
                                                return { value: '@' + u.name, html: u.screenName || u.name };
                                            }));
                                        } else {
                                            resolve([]);
                                        }
                                    })
                                    .catch(function() { resolve([]); });
                                });
                            }
                        }]
                    },
                    input: function(value) {
                        originalTextarea.val(value);
                        $('form[name="write_post"], form[name="write_page"]').trigger('write');
                    },
                    after: function() {
                        $('label[for="text"]').hide();
                    }
                });

                function uploadFileToTypecho(file) {
                    var formData = new FormData();
                    formData.append('file', file);
                    var cid = cidInput.val() || '';
                    var url = new URL(uploadUrl, window.location.origin);
                    url.searchParams.append('cid', cid);

                    fetch(url.toString(), {
                        method: 'POST',
                        body: formData
                    })
                    .then(function(response) { return response.json(); })
                    .then(function(data) {
                        if (data) {
                            var attachment = data[1] || data;
                            var insertText;
                            if (attachment.isImage) {
                                insertText = '![' + attachment.title + '](' + attachment.url + ')';
                            } else {
                                insertText = '[' + attachment.title + '](' + attachment.url + ')';
                            }
                            miraiVditor.insertValue(insertText);
                            if (typeof Typecho !== 'undefined' && Typecho.uploadComplete) {
                                Typecho.uploadComplete(attachment);
                            }
                        }
                    })
                    .catch(function(err) { console.error('Upload failed:', err); });
                }

                $('form[name="write_post"], form[name="write_page"]').on('submit', function() {
                    if (miraiVditor) {
                        originalTextarea.val(miraiVditor.getValue());
                    }
                });

                if (typeof Typecho !== 'undefined') {
                    Typecho.insertFileToEditor = function(file, url, isImage) {
                        if (miraiVditor) {
                            var value;
                            if (isImage) {
                                value = '![' + file + '](' + url + ')';
                            } else {
                                value = '[' + file + '](' + url + ')';
                            }
                            miraiVditor.insertValue(value);
                        }
                    };

                    Typecho.uploadComplete = function(attachment) {
                        Typecho.insertFileToEditor(attachment.title, attachment.url, attachment.isImage);
                    };
                }
            });
        })();
        </script>
        <?php
    }
}

function Mirai_registerEditorHooks() {
    if (!Mirai_featureEnabled('editor')) return;

    $editorType = Mirai_Editor::getEditorType();

    if ($editorType === 'editormd') {
        \Typecho\Plugin::factory('admin/write-post.php')->richEditor = function($post) {
            Mirai_Editor::renderEditorMd($post);
        };
        \Typecho\Plugin::factory('admin/write-page.php')->richEditor = function($page) {
            Mirai_Editor::renderEditorMd($page);
        };
    } elseif ($editorType === 'vditor') {
        \Typecho\Plugin::factory('admin/write-post.php')->richEditor = function($post) {
            Mirai_Editor::renderVditor($post);
        };
        \Typecho\Plugin::factory('admin/write-page.php')->richEditor = function($page) {
            Mirai_Editor::renderVditor($page);
        };
    }
}
