<template>
  <div class="main-container">
    <QuillEditor ref="myQuillEditorRef"
                 theme="snow"
                 v-model:content="data.content"
                 :options="data.editorOption"
                 contentType="delta"
                 @update:content="setValue()"
    />
  </div>
</template>

<script setup lang="ts">
import {QuillEditor, Quill, Delta} from '@vueup/vue-quill'
  import { reactive, onMounted, ref, toRaw, watch, defineProps } from 'vue'
  import '@vueup/vue-quill/dist/vue-quill.snow.css'
  import emitter from '@/utils/emitter'
  import dayjs from 'dayjs'
  import useApis from "@/apis";
  import {useRoute} from "vue-router";
  import {useStore} from "@/store";
  import type {engagementVO} from "@/types/vo.js";
import {ElMessage} from "element-plus";

  const apis = useApis()
  const store = useStore()
  const route = useRoute();

  const assignmentId = Number(route.params.assignmentId);
  const myQuillEditorRef = ref()
  const data = reactive({
    content: {},
    editorOption: {
      modules: {
        toolbar: [
          ['bold', 'italic', 'underline', 'strike'],
          [{ 'size': ['small', false, 'large', 'huge'] }],
          [{ 'align': [] }],
          [{ 'list': 'ordered' }, { 'list': 'bullet' }],
          [{ 'indent': '-1' }, { 'indent': '+1' }],
          [{ 'header': 1 }, { 'header': 2 }],
          ['image'],
          [{ 'direction': 'rtl' }],
          [{ 'color': [] }, { 'background': [] }]
        ]
      },
      placeholder: '请输入内容...'
    }
  })

  // 抛出更改内容
  const setValue = () => {
    const html = toRaw(myQuillEditorRef.value).getHTML()
    emitter.emit('get-html', html)
    const text = toRaw(myQuillEditorRef.value).getText()
    emitter.emit('get-text', text)
    const content1 = toRaw(myQuillEditorRef.value).getContents()
    emitter.emit('get-quill-content', content1)
  }

  /**
   * 合并所有insert内容，因为存在attribute的缘故，原内容被分割成很多个insert
   * @param ops
   */
  const processOps = (ops) => {
    let combinedInsert = '';
    ops.forEach(item => {
      if (item.insert) {
        combinedInsert += item.insert;
      }
    });
    return combinedInsert
  }


  //初始化Quill及行为监控
  const initQuill = () => {

    // 获取quill
    const quill = toRaw(myQuillEditorRef.value).getQuill()
    // 加入工具栏
    if (myQuillEditorRef.value) {
      quill.getModule('toolbar')
    }

    // 文本变化监控
    quill.on(Quill.events.TEXT_CHANGE, (...args) => {
      const [delta, oldDelta, source] = args;
      const deleteOps = delta.ops.filter(op => 'delete' in op);
      // 直接将 ops 数组中的属性合并到一个对象
      const opsObj = {};
      delta.ops.forEach(op => {
        Object.assign(opsObj, op);
      });
      delete opsObj.attributes;
      //有bug，当replace时，既有delete又有insert，此时会被误判为删除操作
      if(deleteOps.length > 0){ //删除操作
        // 获取删除操作的位置和长度
        const deleteStart = delta.ops.find(op => 'retain' in op).retain || 0;   // 删除起始位置
        const deleteLength = delta.ops.find(op => 'delete' in op).delete;       // 删除长度
        const oldContent = processOps(args["1"].ops)// 原内容
        // 提取被删除的具体内容
        const deletedContent = oldContent.slice(deleteStart, deleteStart + deleteLength);

        emitter.emit('change-record', {
          type: "delete",
          retain: 0,
          ...opsObj,
          oldContent,
          deletedContent,
          docLength: quill.getLength() - 1,
          letterCount: (quill.getText().match(/[a-zA-Z\d\u4e00-\u9fa5]/g) || []).length
        })
      } else {
        emitter.emit('change-record', {
          type: "insert",
          retain: 0,
          ...opsObj,
          docLength: quill.getLength() - 1,
          letterCount: (quill.getText().match(/[a-zA-Z\d\u4e00-\u9fa5]/g) || []).length,
          key: args["0"].ops.find(op => 'insert' in op).insert || null
        })
      }
    });

    // 光标变化监控
    quill.on(Quill.events.SELECTION_CHANGE, (...args) => {
      emitter.emit('change-record', {
        type: "cursor_move",
        retain: args["0"].index,  // 将 index 属性重命名为 retain
        length: args["0"].length, // 保留 length 属性
        time: dayjs(new Date()).format("YYYY-MM-DD HH:mm:ss.SSS")
      });
    });
  }

  const fetchData = () => {
    apis.getEngagement(store.user.id, assignmentId)
        .then(res => {
          const engagementData = res.data.data;
          const engagement: engagementVO = Object.assign({}, engagementData);

          // data.content = engagement.textContent
          // const rawEditor = toRaw(myQuillEditorRef.value);
          // rawEditor.setContents(data.content); // 强制设置内容

          if(engagement.quillContent != null){
            data.content = new Delta(JSON.parse(engagement.quillContent));
            const rawEditor = toRaw(myQuillEditorRef.value);
            rawEditor.setContents(data.content); // 强制设置内容
          }
        })
        .catch(err => {
          console.log(err)
        })
  }

// 初始化编辑器
  onMounted(() => {
    initQuill()
    fetchData()
  });

</script>

<script lang="ts">
  export default {
    name: "Editor"
  }
</script>

<style scoped lang="scss">
// 调整样式
.main-container {
  height: 80vh;
  border: solid 2px rgba(199, 199, 199, 0.3);
}

.main-container :deep(.ql-container) {
  height: 95%;
  max-height: 95%;
  background: #fff;
}

.main-container :deep(.ql-toolbar) {
  height: 5%;
  background: #fff;
  min-height: 40px;
}

.main-container :deep(.ql-formats) {
  height: 21px;
  line-height: 21px;
}
</style>