<template>
  <div ref="editor"></div>
</template>

<script setup lang="ts" name="TinyMCE">
import { ref, watch, onMounted, onUnmounted, withDefaults } from 'vue';
import tinymce from 'tinymce';

interface Props {
  modelValue?: string;
  placeholder?: string;
  height?: number;
  type?: string;
  usageType?: string;

  uploadFile?: Function; // 项目的上传接口
}
const props = withDefaults(defineProps<Props>(), {
  type: 'image',
  placeholder: '',
  usageType: '',
  height: 300,
});
const editor = ref<HTMLElement | null>(null);
const editorInstance = ref<tinymce.Editor | null>(null);
const emitModelValue = defineEmits(['update:modelValue']);
onMounted(() => {
  tinymce.init({
    target: editor.value as HTMLElement,
    license_key: 'gpl',
    base_url: '/tinymce',
    external_plugins: {
      editor135: '/tinymce/plugins/editor135/plugin.js',
      preview: '/tinymce/plugins/preview/plugin.js',
      fullscreen: '/tinymce/plugins/fullscreen/plugin.js',
      autosave: '/tinymce/plugins/autosave/plugin.js',
      // importword: '/tinymce/plugins/importword/plugin.js', // https://github.com/Five-great/tinymce-plugins/blob/main/importword/plugin.js
      // tpImportword: '/tinymce/plugins/tpImportword/plugin.js', // https://github.com/tinymce-plugin/tinymce-plugin/blob/main/tpImportword/plugin.js
      // tpImportword: 'https://unpkg.com/tinymce-plugin@0.0.3-beta.22/plugins/tpImportword/plugin.min.js', // https://github.com/tinymce-plugin/tinymce-plugin/blob/main/tpImportword/plugin.js
      link: '/tinymce/plugins/link/plugin.js',
      lists: '/tinymce/plugins/lists/plugin.js',
      pagebreak: '/tinymce/plugins/pagebreak/plugin.js',
      image: '/tinymce/plugins/image/plugin.js',
      media: '/tinymce/plugins/media/plugin.js',
      table: '/tinymce/plugins/table/plugin.js',
      wordcount: '/tinymce/plugins/wordcount/plugin.js',
      code: '/tinymce/plugins/code/plugin.js',
      codesample: '/tinymce/plugins/codesample/plugin.js',
    },
    language_url: '/tinymce/langs/zh_CN.js',
    language: 'zh_CN',
    skin_url: '/tinymce/skins/ui/oxide',
    content_css: '/tinymce/skins/content/default/content.css',
    menubar: false,
    statusbar: true,
    plugins: [],
    skeletonScreen: true,
    toolbar: `editor135 preview print fullscreen restoredraft tpImportword | undo redo |  forecolor backcolor bold italic underline strikethrough link | blocks fontfamily fontsize | \
      alignleft aligncenter alignright alignjustify | outdent indent | numlist bullist | pagebreak | \
      image media table wordcount | code codesample selectall`,
    autosave_ask_before_unload: true,
    autosave_interval: '10s',
    toolbar_mode: 'sliding',
    font_size_formats: '12px 14px 16px 18px 22px 24px 36px 72px',
    height: props.height,
    placeholder: props.placeholder || '',
    branding: false,
    resize: true,
    elementpath: true,
    content_style: '',
    quickbars_selection_toolbar: 'forecolor backcolor bold italic underline strikethrough link',
    quickbars_image_toolbar: 'alignleft aligncenter alignright',
    quickbars_insert_toolbar: false,
    image_caption: true,
    image_advtab: true,
    images_upload_handler(blobInfo: any) {
      const toBase64 = (file: File): Promise<string> => {
        return new Promise((resolve, reject) => {
          const reader = new FileReader();
          reader.readAsDataURL(file); // 读取为 base64
          reader.onload = () => resolve(reader.result as string);
          reader.onerror = (error) => reject(error);
        });
      };

      const toBlobUrl = (file: File): Promise<string> => {
        return Promise.resolve(URL.createObjectURL(file));
      };

      return new Promise(async (resolve, reject) => {
        // 声明上传参数
        const data = new FormData();
        data.append('file', blobInfo.blob(), blobInfo.filename());
        data.append('type', props.type);
        data.append('usage_type', props.usageType);

        window.blobInfo = blobInfo as any;
        console.log(window.blobInfo, '上传文件信息');

        try {
          let res: any = null;
          if (props.uploadFile) {
            res = await props.uploadFile(data); // 你自定义的上传接口
          }
          console.log(res);
          const url = res?.data?.fileinfo?.url;
          if (!url) throw new Error('上传失败');

          // TinyMCE 要求返回 string url
          resolve(url);
        } catch (err) {
          console.error('上传失败，尝试使用 base64 显示', err);

          try {
            const base64 = await toBase64(blobInfo.blob());
            resolve(base64);
          } catch (e) {
            reject(new Error('图片上传失败，且 base64 解析失败'));
          }
        }
      });
    },
    setup(tinymceEditor: any) {
      editorInstance.value = tinymceEditor;
      tinymceEditor.on('init', () => {
        tinymceEditor.getBody().style.fontSize = '14px';

        // 避免 props.modelValue 还没有值就执行了
        setTimeout(() => {
          tinymceEditor.setContent(props.modelValue || '');
        }, 1500);

        const container = tinymceEditor.getContainer();
        const wordCountButton = container.querySelector('button.tox-statusbar__wordcount');
        wordCountButton?.click();
      });
      tinymceEditor.on('change undo redo', () => {
        emitModelValue('update:modelValue', tinymceEditor.getContent());
      });
      tinymceEditor.on('OpenWindow', (e) => {
        // FIX 编辑器在el-drawer中，编辑器的弹框无法获得焦点
        const D = document.querySelector('.el-drawer.open');
        const E = e.target.editorContainer;
        if (D && D.contains(E)) {
          const nowDA = document.activeElement;
          setTimeout(() => {
            document.activeElement.blur();
            nowDA.focus();
          }, 0);
        }
      });
    },
  });
});

watch(
  () => props.modelValue,
  (newVal: any) => {
    if (editorInstance.value && newVal !== editorInstance.value.getContent()) {
      editorInstance.value.setContent(newVal || '');
    }
  },
);

// Cleanup editor instance on component unmount
onUnmounted(() => {
  if (editorInstance.value) {
    tinymce.remove(editorInstance.value);
  }
});
</script>
