<template>
  <div class="AiEditor" @click="editing=true">
    <div ref="AiEditorInstance" style="-webkit-user-select:text;"/>
    <div class="bottomPanel" :class="{fixed:isFullScreen}">
      <slot v-if="$slots.bottom" name="bottom"/>
      <div v-else-if="maxlength" class="fontCount">{{ [editorText.length, maxlength].join(" / ") }}</div>
    </div>
  </div>
</template>

<script>
/**
 * 原组件wangeditor封装
 * 修改者:Kubbo
 */
import E from 'wangeditor'

export default {
  name: "AiEditor",
  inject: {
    elFormItem: {default: ""},
    elForm: {default: ''},
  },
  model: {
    prop: "value",
    event: "change"
  },
  props: {
    value: {type: String, required: true, default: ""},
    placeholder: {default: '请输入正文'},
    conf: Object,
    instance: {type: Function},
    maxlength: Number,
    valid: {type: Boolean, default: true}
  },
  data() {
    return {
      ins: null,
      isFullScreen: false,
      isPasteStyle: true,//粘贴是否携带格式
      origin: "",
      editorText: "",
      editing: false//自动赋值问题,
    }
  },
  computed: {
    validateState() {
      return ['', 'success'].includes(this.elFormItem?.validateState)
    },
    extra() {
      return {
        fullscreen(editor) {
          if (editor?.ins.$toolbarElem) {
            let btn = E.$(`<div class="w-e-menu" data-title="全屏"><i class="w-e-icon-fullscreen"/></div>`)
            btn.on("click", () => {
              editor.isFullScreen = !editor.isFullScreen
              editor.isFullScreen ? editor.ins.fullScreen() : editor.ins.unFullScreen()
            })
            editor.ins.$toolbarElem.append(btn)
          }
        },
        preview(editor) {
          if (editor?.ins.$toolbarElem) {
            let btn = E.$(`<div class="w-e-menu" data-title="预览"><i class="el-icon-monitor"/></div>`)
            btn.on("click", () => {
              editor.$refs.preview.dialog = true
            })
            editor.ins.$toolbarElem.append(btn)
          }
        },
        pasteWithStyle(editor) {
          if (editor?.ins.$toolbarElem) {
            let btn = E.$(`<div class="w-e-menu w-e-active" data-title="粘贴格式"><i class="iconfont iconCopy"/></div>`)
            editor.origin = JSON.parse(JSON.stringify(editor.value))
            btn.on("click", () => {
              editor.isPasteStyle = !editor.isPasteStyle
              if (editor.isPasteStyle) {
                editor.setContent(editor.origin)
                btn.addClass("w-e-active")
              } else {
                editor.origin = JSON.parse(JSON.stringify(editor.value))
                editor.setContent(editor.editorText)
                btn.removeClass("w-e-active")
              }
            })
            editor.ins.$toolbarElem.append(btn)
          }
        }
      }
    },
    customConfig() {
      let init = ["fullscreen", "preview", "pasteWithStyle"]
      if (this.maxlength > 0) init = init.slice(0, 2)
      return {
        debug: true,
        pasteFilterStyle: !this.isPasteStyle,
        showFullScreen: false,
        zIndexFullScreen: 1000,
        zIndex: 98,
        focus: false,
        menus: [],
        init,
        customUploadImg: (files, insert) => {
          this.uploadFile(files, insert)
        },
        customUploadVideo: (files, insert) => {
          this.uploadFile(files, insert)
        },
        onfocus: () => {
          this.editing = true
        },
        onblur: () => {
          this.editing = false
        },
        onchange: html => {
          if (this.maxlength > 0) {
            this.editorText = html?.replace(/<\/?.+?\/?>/g, '')
            if (this.editorText.length > this.maxlength) {
              this.ins.history.revoke()
              // this.editorText = this.editorText.substring(0, this.maxlength)
              // this.setContent(this.editorText)
            }
          } else {
            this.editorText = html
          }
          this.$emit("change", this.editorText)
        },
        pasteTextHandle: str => this.isPasteStyle ? str : str?.replace(/<\/?.+?\/?>/g, ''),
        ...this.conf
      }
    }
  },

  methods: {
    initEditor() {
      let {placeholder, customConfig} = this
      this.ins = new E(this.$refs.AiEditorInstance)
      this.ins.config = {...this.ins.config, ...customConfig, placeholder}
      this.ins.create()
      customConfig.init.map(e => this.extra?.[e]?.(this))
    },
    setContent(data) {
      if (this.ins) {
        this.ins.txt.html(data)
        this.editing = false
      }
    },
    uploadFile(files, insert) {
      files && files.map(e => {
        let formData = new FormData()
        formData.append('file', e)
        this?.instance?.post(`/admin/file/add`, formData).then(res => {
          if (res && res.data) {
            res.data.map(m => {
              let item = m.split(";")
              insert(item[0])
            })
          }
        })
      })
    },
    /**
     * 表单验证
     * @param componentName
     * @param eventName
     * @param params
     */
    dispatch(componentName, eventName, params) {
      let parent = this.$parent || this.$root;
      let name = parent.$options.componentName;

      while (parent && (!name || name !== componentName)) {
        parent = parent.$parent;

        if (parent) {
          name = parent.$options.componentName;
        }
      }
      if (parent) {
        parent.$emit.apply(parent, [eventName].concat(params));
      }
    },
  },
  watch: {
    value(v) {
      this.dispatch('ElFormItem', 'el.form.change', [v]);
      if (v && !this.editing) {
        this.setContent(v)
      }
    },
    placeholder(v) {
      if (this.ins) {
        document.querySelector('.AiEditor .placeholder').innerHTML = v
      }
    },
    editing(v) {
    }
  },
  mounted() {
    !this.ins && this.initEditor()
  }
}
</script>

<style lang="scss" scoped>
::v-deep.AiEditor {
  width: 100%;
  position: relative;

  /* 菜单区 */
  .w-e-toolbar {
    align-items: center;
    flex-wrap: wrap;
    -webkit-box-lines: multiple;

    .w-e-menu {
      line-height: 24px;

      a {
        text-decoration: none;
      }

      &:hover {
        z-index: 10002 !important;
      }
    }
  }

  /* 编辑区 */
  .w-e-text {
    overflow: auto;
    padding: 10px;
    word-break: break-all;

    p {
      margin: 0;
    }
  }

  .fontCount {
    pointer-events: none;
    color: #999;
  }

  .bottomPanel {
    position: absolute;
    bottom: 8px;
    right: 24px;
    z-index: 1999;

    &.fixed {
      position: fixed;
    }
  }

  &.invalid {
    .w-e-text-container, .w-e-toolbar {
      border-color: red !important;
    }

    .fontCount {
      color: red
    }
  }
}
</style>
