<template>
  <div>
    <!-- mask div 蒙层 -->
    <div id="mask"></div>
    <div style="border: 1px solid #DCDFE6; margin-top: 10px;border-radius: 4px">
      <!-- 工具栏 -->
      <Toolbar
        style="border-bottom: 1px solid #DCDFE6"
        :editor="editor"
        :defaultConfig="toolbarConfig"
      />
      <!-- 编辑器 -->
      <Editor
        :style="`height: ${height}px; overflow-y: hidden;`"
        :defaultConfig="defaultEditorConfig"
        v-model="inputValue"
        @onChange="onChange"
        @onCreated="onCreated"
        @onDestroyed="onDestroyed"
        @onMaxLength="onMaxLength"
        @onFocus="onFocus"
        @onBlur="onBlur"
        @customAlert="customAlert"
      />
    </div>
  </div>
</template>

<script>
import { Editor, Toolbar } from '@wangeditor/editor-for-vue'
import '@wangeditor/editor/dist/css/style.css'
import { EditorMixin } from './_CmsFormEditor'

export default {
  name: 'CmsFormEditor',
  components: { Editor, Toolbar },
  mixins: [ EditorMixin ],
  data() {
    return {
      editor: null,
      toolbarConfig: {
        // toolbarKeys: [ /* 显示哪些菜单，如何排序、分组 */ ],
        excludeKeys: [ "fullScreen"/* 隐藏哪些菜单 */ ],
        // modalAppendToBody: true
      },
      editorConfig: {
        placeholder: '请输入内容...',
        autoFocus: true,
        readOnly: this.readOnly,
        // 所有的菜单配置，都要在 MENU_CONF 属性下
        MENU_CONF: {
          // codeSelectLang: {
          //   // codeLangs
          // },
          /* 上传图片 */
          uploadImage: {
            server: '/api/upload', // 服务端地址, 必填，否则上传图片会报错。
            // form-data fieldName ，默认值 'wangeditor-uploaded-image'
            fieldName: 'your-custom-name',
            // 单个文件的最大体积限制，默认为 2M
            maxFileSize: 1024 * 1024, // 1M
            // 最多可上传几个文件，默认为 100
            maxNumberOfFiles: 10,
            // 选择文件时的类型限制，默认为 ['image/*'] 。如不想限制，则设置为 []
            allowedFileTypes: [ 'image/*' ],
            // 自定义上传参数，例如传递验证的 token 等。参数会被添加到 formData 中，一起上传到服务端。
            meta: { ...this.extraData },
            // 将 meta 拼接到 url 参数中，默认 false
            metaWithUrl: false,
            // 自定义增加 http  header
            headers: {
              Accept: 'text/x-json',
              otherKey: 'xxx'
            },
            // 跨域是否传递 cookie ，默认为 false
            withCredentials: true,
            // 超时时间，默认为 10 秒
            timeout: 5 * 1000, // 5 秒
            // 上传之前触发
            onBeforeUpload(file) {
              // file 选中的文件，格式如 { key: file }
              return file
              // 可以 return
              // 1. return file 或者 new 一个 file ，接下来将上传
              // 2. return false ，不上传这个 file
            },
            // 上传进度的回调函数
            onProgress(progress) {
              // progress 是 0-100 的数字
              console.log('progress', progress)
            },
            // 单个文件上传成功之后
            onSuccess(file, res) {
              console.log(`${ file.name } 上传成功`, res)
            },
            // 单个文件上传失败
            onFailed(file, res) {
              console.log(`${ file.name } 上传失败`, res)
            },
            // 上传错误，或者触发 timeout 超时
            onError(file, err, res) {
              console.log(`${ file.name } 上传出错`, err, res)
            },
          },
          /* 图片菜单的配置 onInsertedImage 插入图片之后的回调,onUpdatedImage 更新图片之后的回调,checkImage 校验图片链接,parseImageSrc 转换图片链接*/
          insertImage: {
            onInsertedImage(imageNode) {
              if (imageNode == null) return
              const { src, alt, url, href } = imageNode
              console.log('inserted image', src, alt, url, href)
            },
            checkImage: this.customCheckImageFn, // 也支持 async 函数
            parseImageSrc: this.customParseImageSrc, // 也支持 async 函数
          },
          editImage: {
            onUpdatedImage(imageNode) {
              if (imageNode == null) return
              const { src, alt, url } = imageNode
              console.log('updated image', src, alt, url)
            },
            checkImage: this.customCheckImageFn, // 也支持 async 函数
            parseImageSrc: this.customParseImageSrc, // 也支持 async 函数
          },
          /* 插入链接 */
          insertLink: {
            checkLink: this.customCheckLinkFn, // 也支持 async 函数
            parseLinkUrl: this.customParseLinkUrl, // 也支持 async 函数
          },
          editLink: {
            checkLink: this.customCheckLinkFn, // 也支持 async 函数
            parseLinkUrl: this.customParseLinkUrl, // 也支持 async 函数
          }
        }
      }
    }
  },
  methods: {
    //onUpdatedImage
    onUpdatedImage(file) {
      console.log('----', file)
    },
    onCreated(editor) {
      this.editor = Object.seal(editor) // 【注意】一定要用 Object.seal() 否则会报错
      console.log('--------->>', this.editor.getConfig())
      console.log('--------->>', this.editor.getAllMenuKeys())
      this.editor.on('modalOrPanelShow', modalOrPanel => {
        if (modalOrPanel.type !== 'modal') return
        const { $elem } = modalOrPanel // modal element
        const width = $elem.width()
        const height = $elem.height()
        // set modal position z-index
        $elem.css({
          left: '50%',
          top: '50%',
          marginLeft: `-${ width / 2 }px`,
          marginTop: `-${ height / 2 }px`,
          zIndex: 1000
        })
        // show mask div
        document.getElementById('mask').style.display = 'block'
      })
      this.editor.on('modalOrPanelHide', () => {
        console.log('hide')
        // hide mask div
        document.getElementById('mask').style.display = 'none'
      })
      // click mask div to hide modal
      document.getElementById('mask').addEventListener('click', () => {
        editor.hidePanelOrModal()
      })
    },
    onChange(editor) {
      this.$emit('onChange', editor.getHtml())
    },
    onDestroyed(editor) {
      console.log('onDestroyed', editor)
    },
    onMaxLength(editor) {
      console.log('onMaxLength', editor)
    },
    onFocus(editor) {
      console.log('onFocus', editor)
    },
    onBlur(editor) {
      console.log('onBlur', editor)
    },
    customAlert(info, type) {
      window.alert(`customAlert in Vue demo\n${ type }:\n${ info }`)
    },
    // customPaste(editor, event, callback) {
    //   // console.log('ClipboardEvent 粘贴事件对象', event)
    //   // const html = event.clipboardData.getData('text/html') // 获取粘贴的 html
    //   // console.log(3333, html)
    //   // const text = event.clipboardData.getData('text/plain') // 获取粘贴的纯文本
    //   // const rtf = event.clipboardData.getData('text/rtf') // 获取 rtf 数据（如从 word wsp 复制粘贴）
    //   // 自定义插入内容
    //   // editor.insertText(html)
    //   // 返回 false ，阻止默认粘贴行为
    //   // event.preventDefault()
    //   // callback(false) // 返回值（注意，vue 事件的返回值，不能用 return）
    //   // 返回 true ，继续默认的粘贴行为
    //   callback(true)
    // },
    insertTextHandler() {
      const editor = this.editor
      if (editor == null) return
      editor.insertText(' hello ')
    },
    printEditorHtml() {
      const editor = this.editor
      // if (editor == null) return;
      // console.log(editor.getHtml())
    },
    disableHandler() {
      const editor = this.editor
      if (editor == null) return
      if (this.disabled)
        editor.disable()
    }
  },
  mounted() {
    // 模拟 ajax 请求，异步渲染编辑器
    // setTimeout(() => {
    //   this.html = '<p>Ajax 异步设置内容 HTML</p>'
    // }, 1500)
  },
  beforeDestroy() {
    const editor = this.editor
    if (editor == null) return
    editor.destroy() // 组件销毁时，及时销毁 editor ，重要！！！
  },
  computed: {
    defaultEditorConfig() {
      return Object.assign(this.editorConfig, { placeholder: this.placeholder })
    },
    inputValue: {
      get() {
        return this.value;
      },
      set(val) {
        this.$emit('input', val);
      }
    }
  },
  watch: {
    "disabled": {
      handler() {
        this.disableHandler();
      }
    }
  },
  props: {
    value: [ String ],
    placeholder: String,
    height: {
      type: Number,
      default: 200
    },
    disabled: {
      type: Boolean,
      default: () => {
        return false
      }
    },
    readOnly: [ Boolean ]
  }
}
</script>

<style lang="scss">
.w-e-text-placeholder {
  font-style: italic;
  left: 0;
  top: 0;
  width: 100%;
}

.w-e-text-container {
  .w-e-modal {
    width: 600px !important;
    padding: 40px 15px 0 !important;

    .button-container {
      margin: 0 -15px !important;
      padding-top: 5px;
      border-top: 1px solid #f2f2f2;
      text-align: right;
      padding-right: 5px;
      padding-bottom: 5px;
      background-color: #f2f2f2;
    }
  }

  .babel-container {
    display: flex;
    flex-direction: row;

    span {
      width: 100px;
      text-align: right;
      padding-right: 10px;
    }

    input {
      height: 40px;
    }
  }
}

#mask {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 999;
  background-color: #00000073;
  display: none;
}
</style>