<template>
    <div class="tinymce-box">
        <Editor v-model="content" :api-key="apiKey" :init="init" id="basic-example" />
    </div>
</template>

<script setup lang="ts">
import { onMounted, onBeforeUnmount, ref, computed, watch, nextTick, watchEffect } from "vue";
import type { ComputedRef } from 'vue'
import type { RawEditorOptions } from 'tinymce/tinymce'
import Editor from '@tinymce/tinymce-vue'
import tinymceInstance from 'tinymce/tinymce'
import 'tinymce/themes/silver/theme'
import 'tinymce/icons/default'
import 'tinymce/models/dom'
// 插件
// import 'tinymce/plugins/powerpaste'  付费插件
import 'tinymce/plugins/preview'
import 'tinymce/plugins/searchreplace'
import 'tinymce/plugins/autolink'
import 'tinymce/plugins/directionality'
import 'tinymce/plugins/visualblocks'
import 'tinymce/plugins/visualchars'
import 'tinymce/plugins/fullscreen'
import 'tinymce/plugins/image'
import 'tinymce/plugins/link'
import 'tinymce/plugins/media'
import 'tinymce/plugins/code'
import 'tinymce/plugins/codesample'
import 'tinymce/plugins/table'
import 'tinymce/plugins/charmap'
import 'tinymce/plugins/pagebreak'
import 'tinymce/plugins/nonbreaking'
import 'tinymce/plugins/insertdatetime'
import 'tinymce/plugins/advlist'
import 'tinymce/plugins/lists'
import 'tinymce/plugins/wordcount'
import 'tinymce/plugins/autosave'
import 'tinymce/plugins/emoticons/plugin.min'
import 'tinymce/plugins/emoticons/js/emojis.min'
import 'tinymce/plugins/anchor'
import './customPlugin/index.js'

// 官网文档地址：https://www.tiny.cloud/docs/tinymce/6/

/**
 * @description 类型注解
 * @IEmitProps emit 事件
 * @ToolbarGroup 编辑器工具栏配置
 * @Iprops 父组件传递的数据
 */
interface IEmitProps {
    (e: 'update:modelValue', val: string): void
}
interface ToolbarGroup {
    name?: string
    items: string[]
}
interface Iprops {
    modelValue: string
    // 是否只读
    readonly?: boolean
    toolbar?: string | boolean | string[] | ToolbarGroup[]
    plugins?: string | string[]
    height?: number | string
    width?: number | string
    removedMenuitems?: string
}

// 初始化 编辑器
onMounted(() => {
    tinymceInstance.init({})
})

// 组件销毁
onBeforeUnmount(() => {
    // 销毁对 DOM 的所有内部引用以解决内存泄漏问题
    if (tinymceInstance?.activeEditor?.destroy) {
        tinymceInstance.activeEditor.destroy()
    }
})

// 设置 props 默认值
const props = withDefaults(defineProps<Iprops>(), {
    readonly: false,
    toolbar: () => [
        'blocks fontsize | bold italic underline strikethrough subscript superscript blockquote lineheight | forecolor backcolor removeformat | alignleft aligncenter alignright alignjustify outdent indent | bullist numlist | emoticons link example media table | charmap hr insertdatetime pagebreak | cut copy paste pastetext | selectall visualblocks searchreplace | undo redo restoredraft | print preview fullscreen',
    ],
    plugins:
        'emoticons preview searchreplace autolink directionality visualblocks visualchars fullscreen image media link code codesample table charmap pagebreak nonbreaking anchor insertdatetime advlist lists wordcount autosave example',
    height: 800,
    width: '100%',
    removedMenuitems: 'newdocument codesample anchor code fullscreen fontfamily fontsize',
})

// 编辑器输入值
const content = ref(props.modelValue)

// tinymce 秘钥
const apiKey = ref('jmo5tbgjyyzxnk9rv18wktvly6sts1k4d0mq5dxzamxvox09')

// init 参数
const init = computed(() => {
    return {
        selector: 'textarea#basic-example',
        // skin路径
        skin_url: '/tinymce/skins/ui/oxide',
        // 语言包的路径
        language_url: '/tinymce/langs/zh-Hans.js',
        // 语言类型
        language: 'zh-Hans',
        placeholder: '请输入...',
        min_width: 320,
        min_height: 220,
        // 编辑器宽度
        width: props.width,
        // 编辑器高度
        height: props.height,
        // 编辑器宽高是否可变，false-否,true-高可变，'both'-宽高均可
        resize: 'both',
        // tiny技术支持信息是否显示
        branding: false,
        // 统计字数栏是否显示
        statusbar: true,
        // 编辑器获取焦点是否添加蓝色轮廓
        highlight_on_focus: true,
        // 是否显示升级促销按钮
        promotion: false,
        font_size_formats: '10px 11px 12px 14px 16px 18px 20px 24px 36px',
        // 自定义 editor 样式
        content_style: 'p, div {font-size: 14px; margin: 0px; border:0px ; padding: 0px}',
        content_css: '/tinymce/skins/content/default/content.css',
        // 插件
        plugins: props.plugins,
        // 'emoticons preview searchreplace autolink directionality visualblocks visualchars fullscreen image link media code codesample table charmap pagebreak nonbreaking anchor insertdatetime advlist lists wordcount autosave', // 插件配置 axupimgs indent2em
        // 工具栏
        toolbar: props.toolbar,
        // [
        //   'blocks fontsize | bold italic underline strikethrough subscript superscript blockquote lineheight | forecolor backcolor removeformat | alignleft aligncenter alignright alignjustify outdent indent | bullist numlist | emoticons link image media table | charmap hr insertdatetime pagebreak | cut copy paste pastetext | selectall visualblocks searchreplace | undo redo restoredraft | print preview fullscreen',
        // ],
        // 移除菜单栏 选项 'newdocument codesample anchor code fullscreen fontfamily fontsize'
        removed_menuitems: props.removedMenuitems,
        // 图片是否可粘贴
        paste_data_images: true,
        // 保留粘贴样式 默认为 none
        paste_webkit_styles: 'all',
        // 粘贴内容截取
        paste_preprocess: function (plugin: any, args: { content: string; }) {

            let imageReg = /<img\b[^>]*>/gi;
            let back_ImageReg_1 = /data-lazy-bgimg="[^>]*"/gi;
            let back_imageReg_2 = /background-image:\s*url\([^>]*\);/gi;
            let backImageReg = /data-headimg="[^>]*"/gi;
            args.content = args.content.replaceAll(imageReg, '').replaceAll(backImageReg, '').replaceAll(back_ImageReg_1, '').replaceAll(back_imageReg_2, '')
            // 显示图片的方法
            // const reg = /crossorigin="anonymous"/gi
            // const srcReg = /data-src/gi
            // args.content = args.content.replaceAll(reg, '').replaceAll(srcReg, 'src')

        },
        /**
         * 是否启用合并格式功能
         * 但如果保留嵌套或相同的格式元素很重要，则可以禁用此选项 可选：true / false
         * 主要用来提升性能，减少不必要的 DOM
         */
        paste_merge_formats: false,
        // 上传文件类型 结合 file_picker_callback 使用
        file_picker_types: 'media',
        // 编辑器初始化完成回调
        init_instance_callback: (editor: any) => {
            console.log(`Editor: ${editor.id} 初始化完成`)
            //   console.log(props.modelValue);
        },
        // 此处为图片上传处理函数
        // eslint-disable-next-line @typescript-eslint/no-unused-vars
        // images_upload_handler: (blobInfo: any, _progress: Function) =>
        //   new Promise((resolve) => {
        //     const formData = new FormData()
        //     //   formData.append('file', blobInfo.blob(), blobInfo.filename())
        //     formData.append('file', blobInfo.blob())
        //     let reader = new FileReader() // 本地预览
        //     reader.readAsDataURL(blobInfo.blob())
        //     reader.onloadend = function () {
        //       const imgbase64 = reader.result as string
        //       // 请求成功之后调用 resolve
        //       resolve(imgbase64)
        //     }
        //   }),
        // file_picker_callback: (callback: Function, _value: any, meta: any) => {
        //   // Provide alternative source and posted for the media dialog
        //   // 创建文件选择
        //   let inputElem:HTMLInputElement = document.createElement('input')
        //   inputElem.setAttribute('type', 'file')
        //   inputElem.setAttribute('accept', 'media')
        //   inputElem.click()
        //   inputElem.onchange = () => {
        //     // 获取文件信息
        //     let file = inputElem.files![0]
        //     const formData = new FormData()
        //     formData.append('file', file)
        //     // 所有都转成base64文件流,来自官方文档https://www.tiny.cloud/docs/configure/file-image-upload/#file_picker_callback
        //     let reader = new FileReader()
        //     reader.readAsDataURL(file)
        //     reader.onload = function () {
        //       // Note: Now we need to register the blob in TinyMCEs image blob
        //       // registry. In the next release this part hopefully won't be
        //       // necessary, as we are looking to handle it internally.
        //       //   let id = 'blobid' + new Date().getTime()
        //       //   let blobCache = window.tinymce.activeEditor.editorUpload.blobCache
        //       //   let base64 = (reader.result as string).split(',')[1]
        //       //   console.log('file', file)
        //       //   console.log('base64', base64)
        //       //   let blobInfo = blobCache.create(
        //       //     id,
        //       //     'https://gossv.cfp.cn/videos/mts_videos/medium/VCG2221152458.mp4',
        //       //     base64
        //       //   )
        //       //   blobCache.add(blobInfo)
        //       // call the callback and populate the Title field with the file name
        //       // callback(blobInfo.blobUri(), { title: file.name })
        //       if (meta.filetype === 'media') {
        //         // 请求成功之后调用 callback
        //         // eslint-disable-next-line n/no-callback-literal
        //         callback(
        //           'https://web-assets.dcloud.net.cn/unidoc/zh/%E7%AC%AC1%E8%AE%B2%EF%BC%88uni-app%E4%BA%A7%E5%93%81%E4%BB%8B%E7%BB%8D%EF%BC%89-%20DCloud%E5%AE%98%E6%96%B9%E8%A7%86%E9%A2%91%E6%95%99%E7%A8%8B@20200317%20(3).mp4',
        //           { title: file.name }
        //         )
        //       }
        //     }
        //   }
        // },
    }
})

// 监听 是否只读
watch(
    () => props.readonly,
    (val) => {
        nextTick(() => {
            if (tinymceInstance?.activeEditor?.mode?.set && val) {
                tinymceInstance?.activeEditor.mode.set('readonly')
            }
        })
    },
    { immediate: true }
)
watch(() => props.modelValue, (val) => {
    content.value = val
})
// 定义 emits
const emits = defineEmits<IEmitProps>()

// 内容有变化，就更新内容，将值返回给父组件
watchEffect(() => {
    emits('update:modelValue', content.value)
})
</script>

<style scoped>
.tinymce-box>textarea {
    display: none;
}
</style>
<style>
.tox.tox-tinymce {
    max-width: 100%;
}

.tox .tox-dialog {
    max-width: 712px !important;
    min-height: 500px;
}

.tox .tox-dialog__footer {
    margin-right: 170px;
}

.tox .tox-form {
    border-top: 1px solid #989898;
    border-bottom: 1px solid #989898;
}
</style>: any: { content: string; }
