<script setup lang="ts">
import { computed, nextTick, onMounted, ref, shallowRef, useTemplateRef, watch } from 'vue'
import { createEditorConfig } from './config/editor-config'
import EditorToolbar from './editor-toolbar.vue'
import { downloadFile } from '@/utils/download-file'
import { useI18n } from 'vue-i18n'
import { fetchExportFile } from '@/apis/file'
import ContentOptimizationEdit from './content-optimization-edit.vue'
import { useElementSize } from '@vueuse/core'
import type { Editor } from 'tinymce'

interface Props {
  content: string
  height?: number
  disabled?: boolean
}

const props = withDefaults(defineProps<Props>(), {
  content: '',
  height: 700,
  disabled: false,
})
const emit = defineEmits<{
  input: [value: string]
  init: [value: any]
  creationContentRegenerate: []
}>()

defineExpose({
  getContent,
})

const editorToolbarRef = useTemplateRef<InstanceType<typeof EditorToolbar>>('editorToolbarRef')
const { t } = useI18n()
const editorWrapperRef = useTemplateRef('editorWrapperRef')
const { height: editorWrapperRefHeight } = useElementSize(editorWrapperRef)

const editorConfig = createEditorConfig()

const editor = shallowRef<Editor | null>(null)
const isShowEditor = ref(false)

const articleContentModifyContainerShow = ref(false)

const contentOptimizationEditContainerLocationInfo = ref<{
  position: 'top' | 'middle' | 'bottom'
  positionValue: string
}>({
  position: 'top',
  positionValue: '0px',
})

const editorContent = computed({
  get() {
    return props.content
  },
  set(newVal) {
    emit('input', newVal)
  },
})

watch(
  () => props.content,
  (val: string, prevVal: string) => {
    if (
      editor.value &&
      editor.value.getContent &&
      typeof val === 'string' &&
      val !== prevVal &&
      val !== editor.value.getContent()
    )
      editor.value.setContent(val)
  },
)

onMounted(() => {
  window.tinymce.init({
    ...editorConfig,
    init_instance_callback: (editorInstance) => {
      isShowEditor.value = true
      editor.value = editorInstance

      nextTick(() => {
        props.content && editorInstance.setContent(props.content)
      })

      emit('init', editorInstance)
      if (editorToolbarRef.value) editorToolbarRef.value.editorInit()

      editorInstance.addCommand('creationContentRegenerate', () => {
        emit('creationContentRegenerate')
      })

      editorInstance.on('change keyup undo redo', () => {
        editorContent.value = editorInstance.getContent()
      })

      editorInstance.on('click', () => {
        if (editorToolbarRef.value) editorToolbarRef.value.resetShowPopoverStatus()
      })

      editorInstance.on('change keyup click', () => {
        if (editorToolbarRef.value) {
          editorToolbarRef.value.updateUndoManagerStatus()
          editorToolbarRef.value.updateToolbarActive()
        }
      })

      editorInstance.on('mousedown', (e: MouseEvent) => {
        if (e.button !== 0) return

        if (articleContentModifyContainerShow.value) {
          articleContentModifyContainerShow.value = false
        }

        editorInstance.selection.collapse()
      })

      editorInstance.on('mouseup', (e: MouseEvent) => {
        if (e.button !== 0) return

        const selectionContent = editorInstance.selection.getContent()

        if (selectionContent) {
          const rng = editorInstance.selection.getRng()

          const rects = rng.getClientRects()
          const lastRect = rects[rects.length - 1]

          if (lastRect) {
            /* 其中 46 是当前编辑器文档HTMl距离 外部挂载容器之间产生的高度 */
            const locationHeight = lastRect.bottom + 46 + 10

            if (editorWrapperRefHeight.value - 260 < locationHeight) {
              if (rects[0].top < 200) {
                contentOptimizationEditContainerLocationInfo.value = {
                  position: 'middle',
                  positionValue: '50%',
                }
              } else {
                contentOptimizationEditContainerLocationInfo.value = {
                  position: 'bottom',
                  positionValue: `${editorWrapperRefHeight.value - (rects[0].bottom + 46 + 10) + rects[0].height + 16}px`,
                }
              }
            } else {
              contentOptimizationEditContainerLocationInfo.value = {
                position: 'top',
                positionValue: `${locationHeight}px`,
              }
            }
          }

          articleContentModifyContainerShow.value = true
        }
      })

      editorInstance.on('keyup', () => {
        const selectionContent = editorInstance.selection.getContent()

        if (!selectionContent && articleContentModifyContainerShow.value) {
          articleContentModifyContainerShow.value = false
        }
      })
    },
  })
})

// function editorTitleTextVerify(value: string) {
//   if (value.startsWith('\n') || value.endsWith('\n')) return false

//   return !value.startsWith(' ') && !value.endsWith(' ')
// }

// function getWordCount() {
//   const wordcount = window.tinymce.activeEditor!.plugins.wordcount

//   return wordcount.body.getWordCount()
// }

function getContent() {
  if (!isShowEditor.value) return ''

  const content = editor.value?.getContent() || ''
  const parser = window.tinymce.html.DomParser({ validate: false })

  parser.addNodeFilter('mf-confirmation-box', (nodes) => {
    nodes.forEach((node) => {
      node.remove()
    })
  })

  const rootNode = parser.parse(content)

  return window.tinymce.html.Serializer().serialize(rootNode)
}

function onDownloadFile() {
  const content = getContent()

  fetchExportFile<string>('doc', content).then((res) => {
    if (res.code !== 0) return

    downloadFile(res.data)

    window.$message.success(t('common_module.download_success'))
  })
}
</script>

<template>
  <div v-show="isShowEditor" ref="editorWrapperRef" class="relative h-full w-full min-w-[200px]">
    <div
      id="tinymce-app"
      class="box-border flex h-full flex-col overflow-hidden rounded-lg border-[2px] border-solid border-[#eee] bg-white"
    >
      <div class="toolbar box-content bg-white py-1">
        <EditorToolbar ref="editorToolbarRef" @download-file="onDownloadFile" />
      </div>

      <div class="h-[10px]"></div>

      <div class="grow">
        <textarea class="tinymce-body" />
      </div>
    </div>

    <ContentOptimizationEdit
      v-model:is-show-modal="articleContentModifyContainerShow"
      :editor="editor"
      :location-info="contentOptimizationEditContainerLocationInfo"
    />
  </div>
  <div v-show="!isShowEditor" class="flex h-full w-full items-center justify-center">
    <n-spin size="large" />
  </div>
</template>

<style lang="scss" scoped>
#tinymce-app {
  .toolbar {
    box-shadow:
      0 2px 2px -2px rgba(34, 47, 62, 0.1),
      0 8px 8px -4px rgba(34, 47, 62, 0.07);
  }

  :deep(.n-input) {
    .n-input-wrapper {
      --n-caret-color: #000;

      padding: 0;
      font-size: 18px;
    }

    .n-input__border,
    .n-input__state-border {
      display: none;
    }
  }

  :deep(.tox-tinymce) {
    border: none;
  }
}
</style>
