<template>
  <view id="uni-im-chat-input-box">
    <div contenteditable="true" id="uni-im-chat-input" @blur="onBlur" @focus="onFocus" @input="onInput">
    </div>
  </view>
</template>

<script>
  import uniIm from '@/uni_modules/uni-im/sdk/index.js';
  let inputElement;

  export default {
    name: 'uni-im-chat-input',
    emits: ["update:modelValue", "blur", "focus", "input", "confirm", "cursor"],
    props: {
      modelValue: {
        type: [String, Object],
        default: ""
      },
      placeholder: {
        type: String,
        default: ""
      },
      cursor: {
        type: Number,
        default: 0
      },
      maxlength: {
        type: Number,
        default: 140
      },
      focus: {
        type: Boolean,
        default: false
      }
    },
    data() {
      return {}
    },
    mounted() {
      inputElement = document.getElementById('uni-im-chat-input');
      uniIm.utils.appEvent.onAppActivate(() => {
        // 主窗口激活时设置输入焦点到这里的文本编辑框
        inputElement.focus()
      })
      let shiftIsDown = false;
      window.addEventListener('keydown', (e) => {
        if (e.key == 'Shift') {
          shiftIsDown = true
        }
      })
      window.addEventListener('keyup', (e) => {
        if (e.key == 'Shift') {
          shiftIsDown = false
        }
      })

      let isComposing = false;
      // 输入法开始输入
      inputElement.addEventListener('compositionstart', () =>{
        isComposing = true
        inputElement.isComposing = isComposing;
      });
      // 输入法结束输入
      inputElement.addEventListener('compositionend', () =>{
        isComposing = false
        inputElement.isComposing = isComposing;
      });

      inputElement.addEventListener('keydown', (event) => {
        if (event.key === 'Enter') {
          if (isComposing) {
            console.log('输入法正在输入中，此时回车不发送消息')
            event.preventDefault();
          } else {
            if (shiftIsDown) {
              console.log('shift键处于按下状态，为换行不是confirm发送')
            } else {
              this.$emit('confirm');
              // 防止，回车执行发送的同时执行换行
              event.preventDefault();
            }
          }
        }
      });

      inputElement.addEventListener('paste',async event => {
        // console.log('粘贴', event);
        if (event.clipboardData || event.originalEvent) {
          //某些chrome版本使用的是event.originalEvent
          let clipboardData = event.clipboardData || event.originalEvent.clipboardData;

          // 获取粘贴的图片
          let items = clipboardData.items;
          for (const item of items) {
            if (item.type.indexOf("image") !== -1) {
              event.preventDefault();
              const file = item.getAsFile();
              const reader = new FileReader();
              reader.onload = (readerEvent) => {
                const blobUrl = readerEvent.target.result;
                this.addHtmlToCursor(`<img src="${blobUrl}" />`)
              };
              reader.readAsDataURL(file);
            }
          }

          let htmlString = clipboardData.getData('text/html');
          // console.log('htmlString111',htmlString);
          if (htmlString) {
            event.preventDefault();
            htmlString = await filterHTML(htmlString);
            // console.log('htmlString222', htmlString);
            
            const tmpDom = document.createElement('div');
            tmpDom.innerHTML = htmlString;
            if (tmpDom.innerText > 50000) {
              uni.showModal({
                content: '你粘贴的文本长度超过50000，将被截断。',
                complete: e => {
                  if (e.confirm) {
                    this.addHtmlToCursor(htmlString.substring(0, 50000))
                  }
                }
              });
            } else {
              this.addHtmlToCursor(htmlString)
            }
            // 检查图片加载失败，删除图片
            const imgs = inputElement.querySelectorAll('img');
            for (const img of imgs) {
              img.onerror = () => {
                img.remove();
              }
            }
          } else {
            let text = clipboardData.getData('text');
            try {
              let obj = JSON.parse(text)
              this.addHtmlToCursor(this.arrDomJsonToHtml(obj['uni-im-rich-text-data']))
            } catch (e) {
              this.addHtmlToCursor(text)
            }
            event.preventDefault();
          }
        }
      })

      async function filterHTML(htmlString) {
        // 过滤html字符串，只保留：文字，图片，链接
        // html字符串转dom对象，并深度遍历
        let div = document.createElement('div');
        div.innerHTML = htmlString;
        let arr = [];
        async function deep(node) {
          if (node.nodeType === 1) {
            if (node.tagName === 'IMG') {
              // 只保留src属性
              // 处理图片跨域问题
              if (node.src.indexOf('data:image/png;base64,') != 0 && !node.src.includes('https://im-res.dcloud.net.cn')) {
                const uniImCo = uniCloud.importObject("uni-im-co",{
                  loadingOptions: { // loading相关配置
                  	title: '处理跨域图片...',
                  	mask: true
                  }
                })
                let res = await uniImCo.getImgBase64(node.src)
                // console.log('res.data base64', res.data);
                node.src = res.data
              }
              arr.push(`<img src="${node.src}" />`);
            } else if (node.tagName === 'A') {
              // 只保留href属性
              arr.push(`<a href="${node.href}">${node.innerText}</a>`);
            }
            
            if (node.childNodes.length > 0) {
              for (let i = 0; i < node.childNodes.length; i++) {
               await deep(node.childNodes[i]);
              }
            }
          } else if (node.nodeType === 3) {
            arr.push(node.nodeValue);
          }
        }
        await deep(div);
        return arr.join('');
      }
    },
    watch: {
      modelValue(modelValue, oldModelValue) {
        this.$nextTick(() => {
          // console.log('modelValue', modelValue);
          if (modelValue.length === 0) {
            inputElement.innerHTML = ''
          } else if (typeof modelValue === 'string' && modelValue != this.inputText()) {
            inputElement.innerHTML = modelValue
          } else if (typeof modelValue === 'object' && modelValue.html != inputElement.innerHTML) {
            inputElement.innerHTML = modelValue.html
          }
        });
      },
      cursor(cursor, oldCursor) {
        // console.log('cursor',cursor);
        if (cursor != oldCursor) {
          this.$nextTick(() => {});
        }
      },
      focus(focus, oldFocus) {
        if (focus) {
          inputElement.focus();
        } else {
          inputElement.blur();
        }
      }
    },
    methods: {
      // 设置焦点在最后
      focusToLast() {
        const range = document.createRange();
        const sel = window.getSelection();
        range.selectNodeContents(inputElement);
        range.collapse(false);
        sel.removeAllRanges();
        sel.addRange(range);
        inputElement.focus();
      },
      deleteLeftChar(n = 1) {
        inputElement.focus();
        const selection = window.getSelection();
        if (!selection.isCollapsed) return; //不要删除已选中的内容
        const range = selection.getRangeAt(0).cloneRange();
        if (range.startOffset > 0) {
          range.setStart(range.startContainer, range.startOffset - n);
          range.deleteContents();
          selection.removeAllRanges();
          selection.addRange(range);
        } else if (range.startContainer.previousSibling) {
          const container = range.startContainer;
          const sibling = container.previousSibling;
          range.setStart(sibling, sibling.length - n);
          range.setEnd(sibling, sibling.length);
          range.deleteContents();
          selection.removeAllRanges();
          selection.addRange(range);
        }
        this.exportValue();
      },
      addHtmlToCursor(html) {
        inputElement.focus();
        const selection = window.getSelection();
        if (selection.getRangeAt && selection.rangeCount) {
          let range = selection.getRangeAt(0);
          range.deleteContents();
          var ele = document.createElement("div");
          ele.innerHTML = html;
          var frag = document.createDocumentFragment(),
            node, lastNode;
          while ((node = ele.firstChild)) {
            lastNode = frag.appendChild(node);
          }
          range.insertNode(frag);
          // 设置光标到插入内容之后的位置
          if (lastNode) {
            range = range.cloneRange();
            range.setStartAfter(lastNode);
            range.collapse(true);
            selection.removeAllRanges(); // 清除现有的选择区域
            selection.addRange(range); // 将更新后的范围添加回选择区域
          }
        }
        this.exportValue();
      },
      setHtml(html) {
        inputElement.innerHTML = html
        this.exportValue();
      },
      confirm(){
        this.$emit('confirm');
      },
      exportValue() {

        // 截流 1000毫秒响应一次
        if (this.lock){
          if(this.timer){
            clearTimeout(this.timer);
          }
          this.timer = setTimeout(() => {
            // console.log('执行');
            this.lock = false;
            this.exportValue();
          }, 1000);
          // return console.log('截流');
        }else{
          // console.log('不截流');
          this.lock = true;
        }
        

        let param = '';
        let val = inputElement.innerHTML;
        
        if (val.includes(`<img src="`) || val.includes(`<span class="nickname"`) || val.includes(`<a href="`)) {
          
          param = {
            // "rich-text": //uniIm.utils.parseHtml( 执行比较消耗内存，改为chat页面执行,
            "html": val,
            "text": inputElement.innerText
          }
        } else {
          param = this.inputText()
        }
        this.$emit('update:modelValue', param)
      },
      inputText() {
        return inputElement.innerHTML.replace(/<br\s*\/?>/gi, "\n").replace(/<[^>]+>/g, "");
      },
      onInput(e) {
        // console.log('onInput', e);
        this.$emit('input', {
          "data": e.data,
          "detail": {
            "cursor": 0
          }
        });
        this.exportValue();
      },
      onBlur() {
        // this.$emit('update:focus', false);
        // console.log('blur');
        this.$emit('blur');
      },
      onFocus() {
        // console.log('onFocus');
        this.$emit('focus');
        // this.$emit('update:focus', true);
      },
      setContent(data) {
        if(typeof data === 'string'){
          this.setHtml(data);
        }else{
          inputElement.innerHTML = this.arrDomJsonToHtml(data);
          this.exportValue();
        }
      },
      arrDomJsonToHtml(arr) {
        function parseItem(item) {
          if (item.type === "text") {
            return item.text;
          }
          let html = `<${item.name}`;
          if (item.attrs) {
            for (const key in item.attrs) {
              html += ` ${key}="${item.attrs[key]}"`;
            }
          }
          if (item.children) {
            html += ">";
            for (const child of item.children) {
              html += parseItem(child);
            }
            html += `</${item.name}>`;
          } else {
            html += " />";
          }
          return html;
        }

        let result = "";
        for (const item of arr) {
          result += parseItem(item);
        }
        return result;
      }
    }
  }
</script>

<style lang="scss">
  #uni-im-chat-input-box {
    flex: 1;
    overflow-y: auto;
  }

  #uni-im-chat-input {
    flex: 1;
  }

  #uni-im-chat-input:focus {
    outline: none;
  }

  #uni-im-chat-input ::v-deep img {
    max-width: 90%;
    display: block;
  }

  #uni-im-chat-input ::v-deep .nickname {
    color: #0b65ff !important;
    margin: 0 2px;
    user-select: text;
  }
</style>