<script setup lang="ts">
import type { IEditorConfig, ToolbarOptions } from '@opentiny/fluent-editor/types/config/types'
import type { PropType } from 'vue'
import type MathIframeDailog from './components/math-iframe-dialog.vue'
import type { MyToolbarOption } from './types'
import FluentEditor from '@opentiny/fluent-editor'
import { nextTick, onMounted, ref, watch } from 'vue'
import UpFileDialog from './components/up-file-dialog.vue'
import { editImageAttribute, editVideoAttribute, getEditorConfig, initEditor, MY_OPEN_PROCESSON_IFRAME, upFileList } from './editor-util'
import 'mathlive'
import 'mathlive/static.css'
import 'mathlive/fonts.css'
import '@opentiny/fluent-editor/style.css'
import 'katex/dist/katex.min.css'
import 'quill-toolbar-tip/dist/index.css'

const props = defineProps({
  /** 输入内容 */
  modelValue: { type: String, default: '' },
  /** 工具栏配置 */
  toolbarOption: { type: Object as PropType<MyToolbarOption>, default: undefined },
})
const emit = defineEmits<{
  (e: 'update:modelValue', value: string): void
}>()

const editorRef = useTemplateRef<HTMLDivElement>('editorRef')
const mathIframeDalogRef = useTemplateRef<InstanceType<typeof MathIframeDailog>>('mathIframeDalogRef')
const editorContainerRef = useTemplateRef<HTMLDivElement>('editorContainerRef')
const showToolbar = ref(true)

let editor: FluentEditor | undefined

watch(
  () => props.modelValue,
  (newValue) => {
    if (editor && newValue) {
      if (newValue.startsWith('<p><br></p>') || newValue.startsWith('<p></p>')) {
        emit('update:modelValue', '')
        editor!.root.innerHTML = ''
        return
      }
      nextTick(() => {
        if (editor!.root.innerHTML !== newValue) {
          editor!.root.innerHTML = newValue
        }
      })
    }
  },
)

onMounted(async () => {
  // 得到编辑器配置
  const editorOptions: IEditorConfig = await getEditorConfig({
    toolbarOption: props.toolbarOption,
    /** 点击自定义打开iframe的按钮的回调 */
    [MY_OPEN_PROCESSON_IFRAME]: () => {
      mathIframeDalogRef.value?.show()
    },
  })
  const container = (editorOptions!.modules!.toolbar as ToolbarOptions).container || []
  showToolbar.value = !(container && Array.isArray(container) && container.length > 0)

  // 初始化编辑器
  editor = initEditor(editorRef.value!, editorOptions)
  // 设置内容
  editor.root.innerHTML = props.modelValue

  setTimeout(() => {
    const ImageBlot: any = FluentEditor.import('formats/image')
    // 处理图片给每个图片添加类名和最大宽度
    editor?.scroll.descendants(ImageBlot).forEach((imageBlot: any) => {
      const node = imageBlot.domNode as HTMLImageElement
      editImageAttribute(node, true)
    })
    // 处理视频给每个视频添加类名和最大宽度
    const VideoBlot: any = FluentEditor.import('formats/video')
    editor?.scroll.descendants(VideoBlot).forEach((videoBlot: any) => {
      const node = videoBlot.domNode as HTMLVideoElement
      editVideoAttribute(node, true)
    })
  }, 10)

  editor?.on('text-change', () => {
    nextTick(() => {
      emit('update:modelValue', editor!.root.innerHTML)
    })
  })
})

/**
 * 弹出框关闭时弹出mathlive输入框
 */
function hideIframeDialog() {
  const butt = (editorContainerRef.value?.querySelector('.ql-toolbar.ql-snow .ql-formats  button.ql-formula') || null) as HTMLButtonElement | null
  butt?.click()
}
</script>

<template>
  <div ref="editorContainerRef" class="rest-basic-editor" :class="{ 'hide-toolbar': showToolbar }">
    <div ref="editorRef" />
    <MathIframeDialog ref="mathIframeDalogRef" @hide="hideIframeDialog" />
    <UpFileDialog :up-file-list="upFileList" />
  </div>
</template>

<style lang="scss">
  /* stylelint-disable selector-attribute-name-disallowed-list */
.ql-toolbar.ql-snow {
  // 行高
  .ql-picker.ql-line-height .ql-picker-label:before,
  .ql-picker.ql-line-height .ql-picker-item:before {
    content: '行高(系统默认)';
  }

  .ql-formats .ql-line-height.ql-picker .ql-picker-label[data-value]:before,
  .ql-formats .ql-line-height.ql-picker .ql-picker-item[data-value]:before {
    content: attr(data-value) '倍';
  }

  // 字体
  .ql-picker.ql-font .ql-picker-label:before,
  .ql-picker.ql-font .ql-picker-item:before {
    content: '字体(系统默认)';
  }

  .ql-formats .ql-font.ql-picker .ql-picker-label[data-value]:before,
  .ql-formats .ql-font.ql-picker .ql-picker-item[data-value]:before {
    content: attr(data-value);
  }

  // 字号
  .ql-picker.ql-size .ql-picker-label:before,
  .ql-picker.ql-size .ql-picker-item:before {
    content: '字号(系统默认)';
  }

  .ql-formats .ql-size.ql-picker .ql-picker-label[data-value]:before,
  .ql-formats .ql-size.ql-picker .ql-picker-item[data-value]:before {
    content: attr(data-value);
  }

  // 标题
  .ql-picker.ql-header .ql-picker-label:before,
  .ql-picker.ql-header .ql-picker-item:before {
    content: '标题(默认)';
  }

  .ql-formats .ql-header.ql-picker .ql-picker-label[data-value]:before,
  .ql-formats .ql-header.ql-picker .ql-picker-item[data-value]:before {
    content: '标题(H' attr(data-value) ')';
  }
}
</style>

<style lang="scss" scoped>
  .rest-basic-editor {
  display: flex;
  flex-direction: column;
  width: 100%;
  height: 100%;

  &.hide-toolbar :deep(.ql-toolbar) {
    display: none;
  }

  :deep() {
    .ql-container.ql-snow .toolbar-tip__tooltip {
      position: fixed;
    }

    .ql-container.ql-snow {
      display: flex;
      flex: 1;
      flex-direction: column;
      width: 100%;
      min-height: 0;
      overflow-y: auto;
    }

    .ql-editor {
      overflow-y: visible;
    }

    .ql-toolbar.ql-snow > .ql-formats {
      position: relative;
      padding: 6px 10px;
      margin: 0;
      margin-right: 0;

      &:before {
        position: absolute;
        top: 0;
        left: 0;
        width: 1px;
        height: 100%;
        content: '';
        background: linear-gradient(
          to bottom,
          transparent 0%,
          transparent 26%,
          #dcdada 20%,
          #dcdada 80%,
          transparent 74%,
          transparent 100%
        );
      }

      .ql-picker {
        width: auto;

        .ql-picker-label {
          &:before {
            width: auto;
            padding-right: 14px;
          }

          .icon {
            right: 6px;
          }
        }
      }

      &:first-child {
        padding-left: 0;

        &:before {
          display: none;
          width: 0;
          height: 0;
          padding-left: 0;
          background: transparent;
        }
      }

      > .ql-picker.ql-expanded .ql-picker-options {
        z-index: 3;
        width: auto;
      }
    }
  }
}
</style>
