<template>
  <div class="sel-editor" :style="inputStyle">
    <textarea
      :id="'text-'+id"
      ref="editorRef"
      v-model="modelValue"
    ></textarea>
  </div>
</template>

<script lang="ts" setup>
import { onMounted, ref } from 'vue'
import { randomCode } from 'utils'
import { computed, watch } from 'vue'
import { useUpload } from '../../../hooks/use-upload'
import { EditorConfigOption, UploadOption } from '../types'

defineOptions({
  name: 'SRichText'
})

interface Props {
  modelValue: string
  disabled?: boolean
  editorConfig?: EditorConfigOption
  imageSize?: number
  videoSize?: number
  upload?: UploadOption
  inputStyle: number
  domain?: string
}

const {
  modelValue = '',
  disabled = false,
  editorConfig = () => ({
    placeholder: '请输入...'
  }),
  imageSize = 50,
  videoSize = 100,
  upload = () => ({
    path: '',
    data: [
      {
        key: 'fileArray',
        value: 'file'
      }
    ],
    domain: '',
    listPath: 'data.resultList.0',
    urlKey: 'fileUrl',
    nameKey: 'originalFilename'
  }),
  inputStyle = () => ({}),
  domain = location.origin
} = defineProps<Props>()

const emits = defineEmits([
  'blur',
  'focus',
  'update:modelValue',
  'change',
  'ready'
])
const editorRef = ref()
const id = computed(() => randomCode(8))
const baseUrl = computed(() => domain + '/node-szzt/file/download/2086/R5SBHNKMPXWMLMU26SWDSE/')
onMounted(() => {
  import(baseUrl.value + '/tinymce.min.js').then(() => initialize())
})

const staticConf = computed(() => {
  return {
    selector: `#${ editorRef.value?.id }`,
    document_base_url: baseUrl.value,
    base_url: baseUrl.value,
    language_url: `${ baseUrl.value }langs/zh-Hans.js`,
    language: 'zh-Hans',
    toolbar_sticky: true,
    toolbar_mode: 'sliding',
    branding: false,
    height: '100%',
    resize: false,
    menubar: false,
    plugins: ['table', 'link', 'image', 'media', 'searchreplace'],
    toolbar: [
      { name: 'history', items: ['undo', 'redo'] },
      { name: 'font', items: ['formats', 'fontsize'] },
      {
        name: 'formatting',
        items: ['bold', 'italic', 'underline', 'strikethrough', 'superscript', 'subscript', 'formats', 'removeformat']
      },
      { name: 'headings', items: ['h1', 'h2', 'h3', 'h4', 'h5', 'h6'] },
      { name: 'insert', items: ['table', 'link', 'image', 'media', 'hr', 'searchreplace'] },
      { name: 'color', items: ['forecolor', 'backcolor'] },
      { name: 'alignment', items: ['align'] },
      { name: 'indentation', items: ['outdent', 'indent'] }
    ],
    formats: {
      bold: {
        inline: 'b', styles: { 'font-weight': 'bold' }
      },
      italic: {
        inline: 'i', styles: { 'font-style': 'italic' }
      },
      underline: {
        inline: 'span', styles: { 'text-decoration': 'underline' }
      },
      strikethrough: {
        inline: 'span', styles: { 'text-decoration': 'line-through' }
      }
    }
  }
})
const currentType = ref('')

const accept = computed(() => {
  switch (currentType.value) {
    case 'image':
      return '.png,.jpg,.jpeg,.gif'
    case 'media':
      return '.mp4'
    case 'file':
      return '.doc,.docx,.xls,.xlsx,.ppt,.pptx,.pdf,.txt,.zip,.rar'
  }
})
const size = computed(() => currentType.value === 'image' ? imageSize : videoSize)

const { uploadHandler } = useUpload(accept, size)

const uploadConfig = ref({
  file_picker_types: 'file image media',
  image_title: true,
  automatic_uploads: true,
  paste_data_images: true,
  relative_urls: false,
  remove_script_host: false,
  images_upload_handler: async (blobInfo) => {
    const file = blobInfo.blob()
    currentType.value = 'image'
    const data: any = await uploadHandler(file)
    if (data.url) {
      return data.url
    }
  },
  file_picker_callback: (cb, value, meta) => {
    const input = document.createElement('input')
    input.setAttribute('type', 'file')
    currentType.value = meta.filetype
    if (currentType.value === 'image') {
      input.setAttribute('accept', 'image/*')
    }
    if (currentType.value === 'media') {
      input.setAttribute('accept', 'audio/mp4, video/mp4')
    }
    input.addEventListener('change', async e => {
      const file = e.target.files[0]
      currentType.value = 'image'
      try {
        const data: any = await uploadHandler(file)
        if (data.url) {
          cb(data.url, { title: data.name })
        }
      } catch (error) {
        cb(error)
      }
    })
    input.click()
  }
})
const editorInstance = ref(null)
watch(() => modelValue, () => {
  if (editorInstance.value && !bySelf.value) {
    editorInstance.value.setContent(modelValue)
  }
})
const key = ref('')
const bySelf = ref(false)

function initialize () {
  tinymce.init({
    ...uploadConfig.value,
    ...Object.assign({}, staticConf.value, editorConfig),
    init_instance_callback: editor => {
      editorInstance.value = editor
      editor.on('change', e => {
        bySelf.value = true
        emits('change', editor.getContent())
        emits('update:modelValue', editor.getContent())
      })
      editor.on('blur', e => {
        bySelf.value = false
        emits('blur', editor.getContent())
      })
      editor.on('focus', e => {
        bySelf.value = true
        emits('focus', editor.getContent())
      })
    }
  })
}
</script>
<style lang="scss">
.sel-editor {
  height: 100%;
  width: 100%;

  textarea {
    display: none;
  }

  .tox-tinymce {
    border-radius: 4px;
    background: #fff;
    box-shadow: 0 0 0 1px #e6e6e6;
    border: none;

    .tox-statusbar {
      display: none;
    }
  }
}
</style>
