<template>
  <div class="myRichText">
    <div class="edit-box div_MAX_Height" ref="myEditBox" :style="customStyle" data-type="myEditBox" contenteditable="true" :placeholder="placeholder" v-html="content" :key="keys" :id="keys"
        @blur="saveValue($event)" @change="change($event)" @focus="focus($event)" @click="getFocus($event)" v-on:paste="handlePaste($event)">
    </div>



    <div id="customMenu" ref="customMenu" >
      <template v-if="show">
        <div v-for="item in this.menu" :key="item.name" :class="item.chose?'chose':''" >
            <div @click="clickBtn(item.method)">{{ item.name }}</div>
        </div>
      </template>
        
    </div>
  </div>
</template>

<script>
import mixins from './mixins.js';
export default {
  mixins:[mixins],
  components: {},
  props:{
        value:{
            type:String,
            default:''
        },
        placeholder:{
            type:String,
            default:()=>{
                return "请输入"
            }
        },
        autoFocus:{
          type:Boolean,
          default:false
        },
        keys:{
          type:String,
          default:()=>{
            const len = 6
            const codeList = []
            const chars = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz0123456789'
            const charsLen = chars.length
            for (let i = 0; i < len; i++) {
              codeList.push(chars.charAt(Math.floor(Math.random() * charsLen)))
            }
            return  codeList.join('')
          }
        },
        customStyle:{
          type:String,
        },
        imgStyle:{
          type:Object,
          default:()=>{
            return {
              width:'80px',
              height:'80px'
            }
          }
        },
        checkImage:{
          type:Boolean,
          default:true
        },
        editModel:{
          type:String,
          default:'edit'
        }
    },
  data() {
    return {
        content: this.value||"", // 内容,
        beforeChange:'',
        menu :[
          {
            name: "高亮",
            method: "highlight",
          },
          // {
          //   name: "取消全部高亮",
          //   method: "cancel",
          // }
        ],
        selectObj:null,
        show:false,
          imageStyle:{
              width:this.imgStyle.width || '80px',
              height:this.imgStyle.height || '80px'
          }
    };
  },
  watch: {
    value(val){
      this.content = val
    },
    show(val){
      if(!val){
        // this.$refs.myEditBox.focus()
        this.moveToEnd()
      }
    }
  },
  computed: {},
  created() {},
  mounted() {
    var that = this
    if(this.editModel == 'clean'){
      this.imageStyle = {
        width:'98%',
        height:'auto'
      }
    }else{
      this.$refs.myEditBox.addEventListener('contextmenu', function(event) {
        event.preventDefault(); // 取消默认的右击菜单显示行为
        that.showCustomMenu(event)
      });
    }
    
    
    this.setFocus()
    // 当点击任意地方或者按下ESC键时，隐藏菜单
    // window.onclick = this.hideCustomMenu
    var that = this
    window.addEventListener('click',function(event){
      var customMenu = that.$refs.customMenu
      if (customMenu && event.target != customMenu && !customMenu.contains(event.target)) {
          customMenu.style.display = "none";
          that.show = false
      }
      
    })
    window.onkeydown = this.checkKeyPress
    this.setFocus()
  },
  methods: {
    setFocus(){
      if(this.autoFocus){
        // this.$refs.myEditBox.focus()
        this.$nextTick(()=>{
          this.moveToEnd()
        })
        
      }
    },
    moveToEnd() {  
      const editableDiv = this.$refs.myEditBox; 
      try{
        if(editableDiv.lastChild) {
          const range = document.createRange();
          range.selectNodeContents(editableDiv)
          range.collapse(false)
          const selection = window.getSelection();  
          // 将范围设置为从文本末尾到文本末尾（实际上是一个空范围，但用于设置光标位置）  
          // range.setStart(editableDiv.lastChild, editableDiv.lastChild.textContent.length);  
          // range.setEnd(editableDiv.lastChild, editableDiv.lastChild.textContent.length);  
      
          // 应用选择范围  
          selection.removeAllRanges();  
          selection.addRange(range);  
        }
      }catch{
        
      }
      
      // 确保光标可见（在某些浏览器中可能需要）  
        editableDiv.focus();  
  
      
    }, 

    clickBtn(method){
     
      var SplitHtmls = this.SplitHtmlTag1(this.$refs.myEditBox.innerHTML)
      var html = this.$refs.myEditBox.innerHTML
      if(method == 'cancel'){
        html = html.replace(/<highlight>/g,'').replace(/<\/highlight>/g,'')
      }else{
        html = this.changeHtml(SplitHtmls,method)
      }
      //  var html = this.addTag(SplitHtmls,method)
      this.content = html
      this.show = false
      
      this.$emit('input',html)
      // this.$emit('blur',html)
      this.$emit('change',html)
      this.close()
      
    },


   
    showCustomMenu(event) {
      if(this.editModel == 'clean'){
        return
      }
      var obj = document.getSelection()
      if(obj.anchorOffset == 0 && obj.extentOffset == 0){
        return false
      }
      this.selectObj = {
        anchorNode: obj.anchorNode,
        anchorOffset: obj.anchorOffset,
        extentNode: obj.extentNode,
        extentOffset: obj.extentOffset,
        focusNode:obj.focusNode,
        focusOffset:obj.focusOffset,
        isCollapsed: obj.isCollapsed,
        rangeCount: obj.rangeCount,
        type: obj.type,
        text:obj.toString()
      }
      //判断是否已经突出显示
      if (this.selectObj.anchorNode.isEqualNode(this.selectObj.extentNode)) {
        var tags = this.getParentNode(this.selectObj)
        if(tags.length != 0){
          for(var i = 0;i<tags.length;i++){
            var index = this.menu.findIndex(item=>{
              item.chose = false
              return item.method == tags[i].tagName.toLowerCase()
            })
            if(index!=-1){
              this.menu[index].chose = true
              break
            }else{
              
            }
          }
          
        }
      } else {
          // console.log("两个DOM元素不相同");
      }
      this.show = false
      var { startIndex,endIndex } = this.getLocation(this.$refs.myEditBox,this.selectObj)
      this.selectObj.startIndex = startIndex
      this.selectObj.endIndex = endIndex
      this.$nextTick(()=>{
        this.show = true
        var customMenu = this.$refs.customMenu
        var xPos = event.clientX + "px";
        var yPos = event.clientY + "px";
        customMenu.style.display = "block";
        customMenu.style.left = xPos;
        customMenu.style.top = yPos;
      })
      
    },
    hideCustomMenu(event) {
      var customMenu = this.$refs.customMenu
      if (event.target != customMenu && !customMenu.contains(event.target)) {
          customMenu.style.display = "none";
      }
    },
    close(){
        var customMenu = this.$refs.customMenu
        customMenu.style.display = 'none';
    },
    checkKeyPress(e) {
      var customMenu = this.$refs.customMenu
      e = e || window.event;
      if (e.keyCode == 27) { // ESC键的keycode值为27
          customMenu.style.display = "none";
          this.show = false
      }
      if (e.keyCode === 13) {
        if(this.editModel == 'clean'){
          return
        }
        // return
          e.preventDefault(); // 阻止默认操作
          document.execCommand("insertHTML", false, "<br><br>"); // 插入换行
      }
    },
    //粘贴
   async handlePaste(e){
    var event = e || window.event
    event.preventDefault();
      const items = (event.clipboardData || window.clipboardData).items;
      let file = null;
      if (!items || items.length === 0) {
        this.$message.error("当前浏览器不支持本地");
        return;
      }
      for (let i = 0; i < items.length; i++) {
        if (items[i].type.indexOf("text") !== -1) {
          var text =  (event.originalEvent || event).clipboardData.getData('text/plain') ||'';
          // text = text.replace(/\n{1,}/g,'<br>').replace(/&lt;/g,'<').replace(/&gt;/g,'>')
          text = text.replace(/\n{1,}/g,'<br>')
          if(this.editModel != 'clean'){
            text = this.parsedText(text)
          }
          
          document.execCommand('insertHTML', true, text)

          // var text2 = `<span>${text}</span>`
          // this.setCursor(event,text2,1)
          break;
        }
        // if(items[i].type.indexOf("text/html") !== -1){
        //   var string = (event.originalEvent || event).clipboardData.getData('text/html')

				// const srcRegex = /<img\s+(?:[^>]*?\s+)?src\s*=\s*(["'])((?:[^\1"]|\\\1|.)*?)\1/g
				// const result = [...string.matchAll(srcRegex)]
				// var src = result.map(v => v[2])[0]
        // console.log(src)
        // var reader  = new FileReader()
        // var srcBase64 = reader.readAsDataURL(src)
        // // var srcBase64 =await this.urlToBase64(src)
        //   console.log(srcBase64)
        //   continue;
        // }
        if (items[i].type.indexOf("image") !== -1) {
          var e = event || window.event
          e.preventDefault();
          file = items[i].getAsFile();
          break;
        }
      }
      if (!file) {
        return;
      }
      var str = await this.fileToBase64(file)
      var randNum=Math.floor(Math.random()*(9999-1000))+1000;
      if(!this.checkImage || this.editModel == 'clean'){
        var new_img = '<img key="'+ randNum +'" src="' + str + '" style="width:'+ this.imageStyle.width +';height: '+ this.imageStyle.height +';border: 1px solid #f9f6f675;vertical-align:middle"/>';
      }else{
        var new_img = '<img key="'+ randNum +'" src="' + str + '" onClick="vm.checkImg(event)" style="width:'+ this.imageStyle.width +';height: '+ this.imageStyle.height +';border: 1px solid #f9f6f675;vertical-align:middle"/>';
      }
      // document.execCommand('insertText', false, new_img)
      // var alltext =  this.$refs.myEditBox.innerHTML
      const parser = new DOMParser();  
      const doc = parser.parseFromString(new_img, "text/html");  
      var alltext =  doc.body.innerHTML
      document.execCommand('insertHTML', false, alltext )
      // this.$refs.myEditBox.innerHTML = alltext
      // 创建新的光标对象
//       var range = document.createRange();
//                 // 将光标对象的范围界定为新建的表情节点
//                 range.selectNodeContents(new_img);
//                 // 定位光标位置在表情节点的最大长度位置
//                 range.setStart(new_img, new_img.length);

//                 // 将选区折叠为一个光标
//                 range.collapse(true);
//                 // 清除所有光标对象
//                 selection.removeAllRanges();
//                 // 添加新的光标对象
//                 selection.addRange(range);
// console.log(event.target.innerHTML)
      // var index = window.getSelection().getRangeAt(0)

      // this.setCursor(event,new_img,2)
      // var indexText = this.getColumn(event.target,window.getSelection())
      // var index2 = 0
      // var str2 = content.slice(0, indexText) + new_img + content.slice(indexText);
      // event.target.innerHTML = str2
      // this.$nextTick(()=>{
      //   var selectedText = window.getSelection();
      // var selectedRange = document.createRange();
      // try{
      //   for(var i=0;i<event.target.childNodes.length;i++){
      //     if(event.target.childNodes[i].outerHTML == new_img){
      //       index2 = i
      //       throw new Error()
      //     }
      //   }
      // }catch{

      // }
      // selectedRange.setStart(event.target,index2+1);
      // selectedRange.collapse(true);
      // selectedText.removeAllRanges();
      // selectedText.addRange(selectedRange);
      // event.target.parentNode.focus(); 
      // })
      
      // this.saveValue(event)
      // var selection = window.getSelection()
      // window.getSelection().addRange(this.index)
      // console.log(window.getSelection().getRangeAt(0))
     
    },
    /**
 * 根据图片的url转换对应的base64值
 * @param { String } imageUrl 如：http://xxxx/xxx.png
 * @returns base64取值
 */
async urlToBase64(imageUrl) {
    return new Promise((resolve, reject) => {
      let canvas = document.createElement('canvas')
      const ctx = canvas.getContext('2d')
      let img = new Image()
      img.crossOrigin = 'Anonymous' // 解决Canvas.toDataURL 图片跨域问题
      img.src = imageUrl
      img.onload = function() {
        canvas.height = img.height
        canvas.width = img.width
        ctx.fillStyle = '#fff' // canvas背景填充颜色默认为黑色
        // ctx.fillRect(0,0,img.width,img.height)
        ctx.drawImage(img, 0, 0,img.width,img.height) // 参数可自定义
        const dataURL = canvas.toDataURL('image/jpeg', 1) // 获取Base64编码
        resolve(dataURL)
        canvas = null // 清除canvas元素
        img = null // 清除img元素
      }
      img.onerror = function() {
        reject(new Error('Could not load image at ' + imageUrl))
      }
    })
},
    //设置光标位置
    setCursor(event,str,type){
      // console.log(event)
          var content = event.target.innerHTML
          // previousSibling
          var indexText = this.getColumn(event.target,window.getSelection())
          var index2 = 0
          var childNodes = event.target.childNodes
          if(!content){
            if(event.target.nodeName == 'BR'){
              const span = document.createElement('span');
              span.innerHTML = str;
              event.target.parentNode.insertBefore(span,event.target)
              var selectedRange = document.createRange();
              selectedRange.setStart(event.target,index2);
              return false
            }else{
              event.target.innerHTML = str
            }
          }else{
            content = content.replace(/&nbsp;/g,'\r')
            var str2 = content.slice(0, indexText) + str + content.slice(indexText);
            event.target.innerHTML = str2.replace(/\r/g,'&nbsp;')
          }
          
            // console.log(event.currentTarget.childNodes)
            // if(event.target.nodeName == 'BR'){
            //   event.target.nodeName = 'SPAN'
            //   event.target.innerHTML = '</br>' + str2
            // }
          this.$nextTick(()=>{
            var selectedText = window.getSelection();
          var selectedRange = document.createRange();
          try{
            for(var i=0;i<childNodes.length;i++){
                var html = childNodes[i].outerHTML
                if(type == 1){
                  if(html){
                    html = html.replace(/\r{1,}|\n{1,}|\r\n{1,}/g,'')
                    str = html.replace(/\r{1,}|\n{1,}|\r\n{1,}/g,'')
                  }
                }
                if(html == str){
                  index2 = i
                  throw new Error()
                }
              
            }
          }catch{

          }
          selectedRange.setStart(event.target,index2+1);
          selectedRange.collapse(true);
          selectedText.removeAllRanges();
          selectedText.addRange(selectedRange);
          event.target.parentNode.focus(); 
          })
    },
  
    // 将file文件上传转化为base64进行显示
    fileToBase64(file) {
        return new Promise((resolve, reject) => {
            const reader = new FileReader()
            //开始读文件
            reader.readAsDataURL(file)
            reader.onload = () => resolve(reader.result)
            // 失败返回失败的信息
            reader.onerror = error => reject(error)
        })
    },
    getFocus(event){
      event.target.parentNode.focus();
    },
    saveValue(event){
      if(this.show){
        return 
      }
        var a  = event.target.innerHTML
        this.$emit('input',a)
        this.$emit('blur',a)
        if(a != this.beforeChange){
          this.$emit('change',a)
        }
    },

    // input(event){
    //   var a  = event.target.innerHTML
    //   this.$emit('input',a)
    // },
    focus(event){
      this.beforeChange = event.target.innerHTML
    },
  },
};
</script>
<style lang="scss" scoped>
.myRichText{
  position: relative;
}
#customMenu {
  user-select:none;
  background: #fff;
  color: #34495e;
  box-shadow: 0px 2px 4px 0px rgba(0, 0, 0, 0.2);
  min-width: 100px;
  text-align: center;
  z-index: 9999;
   display: none; /* 初始状态下不显示 */
   position: fixed;
   &>div{
    padding:10px;
    line-height: 25px;
    border-bottom: 1px solid #E4E7ED;
    cursor: pointer;
   }
   &>div:last-child{
    border-bottom: none;
   }
   &>div:hover{
    background: #edf6ff;
   }
   .chose{
    background: #edf6ff;
   }
}
.edit-box{
  overflow-x: hidden;
    text-overflow: ellipsis;
    text-wrap: wrap;
    text-align: left;
    padding: 10px 15px;
    // min-height:27px;
    line-height: 1.5;
    outline: #dcdfe6;
    border:1px solid var(--bg);
    border-radius:5px;
    div{
      height:30px !important;
      line-height: 30px !important;
    }
}
.edit-box:empty::before {
    content: attr(placeholder);
    // margin-left:15px;
    font-style: normal;
    white-space: nowrap;
    color: #cacdd4;
}
// .edit-box:focus::before {
//     content:none;
// }
</style>