<script>
import { useScopedSlot, messageToHtml, clearHtmlExcludeImg } from "utils";
import ChatArea from "chatarea";
// 引入css样式
import "chatarea/lib/ChatArea.css";
const command = (command, val) => {
  document.execCommand(command, false, val);
};
const selection = window.getSelection();
let range;
let emojiData = [];
let isInitTool = false;
export default {
  name: "LemonEditor",
  inject: {
    IMUI: {
      from: "IMUI",
      default() {
        return this;
      },
    },
  },
  components: {},
  props: {
    tools: {
      type: Array,
      default: () => [],
    },
    sendText: {
      type: String,
      default: "发 送",
    },
    wrapKey: {
      type: Function,
      default: function(e) {
        return e.keyCode == 13 && e.ctrlKey === true;
      },
    },
    sendKey: {
      type: Function,
      default(e) {
        return e.keyCode == 13 && e.ctrlKey == false && e.shiftKey == false;
      },
    },
  },
  data() {
    this.clipboardBlob = null;
    return {
      //剪切板图片URL
      clipboardUrl: "",
      submitDisabled: true,
      //proxyTools: [],
      accept: "",
      chatArea: null,
    };
  },
  created() {
    this.IMUI.$on("change-contact", () => {
      this.closeClipboardImage();
    });
    this.$nextTick(() => {
      this.chatArea = new ChatArea({
        elm: this.$refs.textarea, // 从dom上抓取一个元素将其改造
        userList: [
          // 当输入@键时弹出人员选择的列表
        ],
        userProps: {
          // 人员列表数据结构 转接差异key值
          id: "id",
          name: "displayName",
          avatar: "avatar",
          pinyin: "name_py",
        },
        placeholder: "",
        needCallSpace: true,
        wrapKeyFun: event => this.wrapKey(event),
        sendKeyFun: event => this.sendKey(event),
      });

      this.chatArea.richText.addEventListener("blur", e => {
        setTimeout(this.chatArea.winClick, 200);
      });
      // 监听发送键
      this.chatArea.enterSend = () => {
        // 在此处执行你对发送消息的处理
        if (this.submitDisabled == false) {
          this._handleSend();
        }
      };
    });
  },
  render() {
    const toolLeft = [];
    const toolRight = [];
    this.proxyTools.forEach(({ name, title, render, click, isRight }) => {
      click = click || new Function();
      const classes = [
        "lemon-editor__tool-item",
        { "lemon-editor__tool-item--right": isRight },
      ];
      let node;
      if (name == "emoji") {
        node =
          emojiData.length == 0 ? (
            ""
          ) : (
            <lemon-popover class="lemon-editor__emoji">
              <template slot="content">{this._renderEmojiTabs()}</template>
              <div class={classes} title={title}>
                {render()}
              </div>
            </lemon-popover>
          );
      } else {
        node = (
          <div class={classes} on-click={click} title={title}>
            {render()}
          </div>
        );
      }
      if (isRight) {
        toolRight.push(node);
      } else {
        toolLeft.push(node);
      }
    });

    return (
      <div class="lemon-editor">
        {this.clipboardUrl && (
          <div class="lemon-editor__clipboard-image">
            <img src={this.clipboardUrl} />
            <div>
              <lemon-button
                style={{ marginRight: "10px" }}
                on-click={this.closeClipboardImage}
                color="grey"
              >
                取消
              </lemon-button>
              <lemon-button on-click={this.sendClipboardImage}>
                发送图片
              </lemon-button>
            </div>
          </div>
        )}
        <input
          style="display:none"
          type="file"
          multiple="multiple"
          ref="fileInput"
          accept={this.accept}
          onChange={this._handleChangeFile}
        />
        <div class="lemon-editor__tool">
          <div class="lemon-editor__tool-left">{toolLeft}</div>
          <div class="lemon-editor__tool-right">{toolRight}</div>
        </div>
        <div class="lemon-editor__inner">
          <div
            class="lemon-editor__input"
            ref="textarea"
            on-keyup={this._handleKeyup}
            on-keydown={this._handleKeydown}
            on-paste={this._handlePaste}
            on-click={this._handleClick}
            on-input={this._handleInput}
            on-drop={this._handleDrop}
            spellcheck="false"
          />
        </div>
        <div class="lemon-editor__footer">
          <div class="lemon-editor__tip">
            {useScopedSlot(
              this.IMUI.$scopedSlots["editor-footer"],
              "使用 ctrl + enter 换行",
            )}
          </div>
          <div class="lemon-editor__submit">
            <lemon-button
              disabled={this.submitDisabled}
              on-click={this._handleSend}
            >
              {this.sendText}
            </lemon-button>
          </div>
        </div>
      </div>
    );
  },
  computed: {
    proxyTools() {
      if (!this.tools) return [];
      const defaultTools = [
        {
          name: "emoji",
          title: "表情",
          click: null,
          render: menu => {
            return <i class="lemon-icon-emoji" />;
          },
        },
        {
          name: "uploadFile",
          title: "文件上传",
          click: () => this.selectFile("*"),
          render: menu => {
            return <i class="lemon-icon-folder" />;
          },
        },
        {
          name: "uploadImage",
          title: "图片上传",
          click: () => this.selectFile("image/*"),
          render: menu => {
            return <i class="lemon-icon-image" />;
          },
        },
      ];
      let tools = [];
      if (Array.isArray(this.tools)) {
        const indexMap = {
          emoji: 0,
          uploadFile: 1,
          uploadImage: 2,
        };
        const indexKeys = Object.keys(indexMap);
        tools = this.tools.map(item => {
          if (indexKeys.includes(item.name)) {
            return {
              ...defaultTools[indexMap[item.name]],
              ...item,
            };
          }
          return item;
        });
      } else {
        tools = defaultTools;
      }
      return tools;
    },
  },
  methods: {
    closeClipboardImage() {
      this.clipboardUrl = "";
      this.clipboardBlob = null;
    },
    sendClipboardImage() {
      if (!this.clipboardBlob) return;
      this.$emit("upload", this.clipboardBlob);
      this.closeClipboardImage();
    },
    saveRangeToLast() {
      if (!range) {
        range = document.createRange();
      }
      range.selectNodeContents(textarea.value);
      range.collapse(false);
      selection.removeAllRanges();
      selection.addRange(range);
    },
    inertContent(val, toLast = false) {
      if (toLast) saveRangeToLast();
      this.focusRange();
      command("insertHTML", val);
      this.saveRange();
    },
    saveRange() {
      range = selection.getRangeAt(0);
    },
    focusRange() {
      this.$refs.textarea.focus();
      if (range) {
        selection.removeAllRanges();
        selection.addRange(range);
      }
    },
    _handleClick() {
      this.saveRange();
    },
    _handleInput() {
      this._checkSubmitDisabled();
    },
    _handleDrop(e) {
      e.preventDefault();
      const { dataTransfer } = e;
      const { files } = dataTransfer;
      Array.from(files).forEach(file => {
        this.$emit("upload", file);
      });
    },
    _renderEmojiTabs() {
      const renderImageGrid = items => {
        return items.map(item => (
          <img
            src={item.src}
            title={item.title}
            class="lemon-editor__emoji-item"
            on-click={() => this._handleSelectEmoji(item)}
          />
        ));
      };
      if (emojiData[0].label) {
        const nodes = emojiData.map((item, index) => {
          return (
            <div slot="tab-pane" index={index} tab={item.label}>
              {renderImageGrid(item.children)}
            </div>
          );
        });
        return <lemon-tabs style="width: 412px">{nodes}</lemon-tabs>;
      } else {
        return (
          <div class="lemon-tabs-content" style="width:406px">
            {renderImageGrid(emojiData)}
          </div>
        );
      }
    },
    _handleSelectEmoji(item) {
      this.chatArea.insertHtml(
        `<img emoji-name="${item.name}" src="${item.src}"></img>`,
      );
      this._checkSubmitDisabled();
    },
    async selectFile(accept) {
      this.accept = accept;
      await this.$nextTick();
      this.$refs.fileInput.click();
    },
    _handlePaste(e) {
      e.preventDefault();
      const clipboardData = e.clipboardData || window.clipboardData;
      const text = clipboardData.getData("Text");
      if (text) {
        this.submitDisabled = false;
      } else {
        const { blob, blobUrl } = this._getClipboardBlob(clipboardData);
        this.clipboardBlob = blob;
        this.clipboardUrl = blobUrl;
      }
    },
    _getClipboardBlob(clipboard) {
      let blob, blobUrl;
      for (var i = 0; i < clipboard.items.length; ++i) {
        if (
          clipboard.items[i].kind == "file" &&
          clipboard.items[i].type.indexOf("image/") !== -1
        ) {
          blob = clipboard.items[i].getAsFile();
          blobUrl = (window.URL || window.webkitURL).createObjectURL(blob);
        }
      }
      return { blob, blobUrl };
    },
    _handleKeyup(e) {
      this.saveRange();
      this._checkSubmitDisabled();
    },
    _handleKeydown(e) {
      if (e.keyCode == 13 || (e.keyCode == 13 && e.shiftKey)) {
        e.preventDefault();
      }
      if (this.wrapKey(e)) {
        e.preventDefault();
        command("insertLineBreak");
      }
    },
    getFormatValue() {
      // return toEmojiName(
      //   this.$refs.textarea.innerHTML
      //     .replace(/<br>|<\/br>/, "")
      //     .replace(/<div>|<p>/g, "\r\n")
      //     .replace(/<\/div>|<\/p>/g, "")
      // );
      return this.IMUI.emojiImageToName(this.chatArea.getHtml());
    },
    _checkSubmitDisabled() {
      this.submitDisabled = !clearHtmlExcludeImg(
        this.chatArea.getHtml().trim(),
      );
    },
    _handleSend(e) {
      const text = this.getFormatValue();
      this.$emit("send", text);
      this.clear();
      this._checkSubmitDisabled();
    },
    _handleChangeFile(e) {
      const { fileInput } = this.$refs;
      Array.from(fileInput.files).forEach(file => {
        this.$emit("upload", file);
      });
      fileInput.value = "";
    },
    clear() {
      this.chatArea.clear();
    },
    initEmoji(data) {
      emojiData = data;
      this.$forceUpdate();
    },
    setValue(val) {
      this.chatArea.clear(this.IMUI.emojiNameToImage(val));
      this._checkSubmitDisabled();
    },
  },
};
</script>
<style lang="stylus">
@import '~styles/utils/index'
gap = 10px;
+b(lemon-editor)
  height 200px
  position relative
  flex-column()
  +e(tool)
    display flex
    height 40px
    align-items center
    justify-content space-between
    padding 0 5px
  +e(tool-left){
    display flex
  }
  +e(tool-right){
    display flex
  }
  +e(tool-item)
    cursor pointer
    padding 4px gap
    height 28px
    line-height 24px;
    color #999
    transition all ease .3s
    font-size 12px
    [class^='lemon-icon-']
      line-height 26px
      font-size 22px
    &:hover
      color #333
    +m(right){
      margin-left:auto;
    }
  +e(inner)
    flex 1
    overflow-x hidden
    overflow-y auto
    scrollbar-light()
  +e(clipboard-image)
    position absolute
    top 0
    left 0
    width 100%
    height 100%
    flex-column()
    justify-content center
    align-items center
    background #f4f4f4
    z-index 1
    img
      max-height 66%
      max-width 80%
      background #e9e9e9
      //box-shadow 0 0 20px rgba(0,0,0,0.15)
      user-select none
      cursor pointer
      border-radius 4px
      margin-bottom 10px
      border 3px dashed #ddd !important
      box-sizing border-box
    .clipboard-popover-title
      font-size 14px
      color #333
  +e(input)
    height 100%
    box-sizing border-box
    border none
    outline none
    padding 0 gap
    scrollbar-light()
    .chat-rich-text
      border-radius 0
      min-height 100px
      padding 0
    .chat-rich-text *
    .chat-area-pc *
      font-size 14px
    p,div
      margin 0
    img
      height 20px
      padding 0 2px
      pointer-events none
      position relative
      top -1px
      vertical-align middle
  +e(footer)
    display flex
    height 52px
    justify-content flex-end
    padding 0 gap
    align-items center
  +e(tip)
    margin-right 10px
    font-size 12px
    color #999
    user-select none
  +e(emoji)
    user-select none
    .lemon-popover
      background #f6f6f6
    .lemon-popover__content
      padding 0
    .lemon-popover__arrow
      background #f6f6f6
    .lemon-tabs-content
      box-sizing border-box
      padding 8px
      height 200px
      overflow-x hidden
      overflow-y auto
      scrollbar-light()
      margin-bottom 8px
  +e(emoji-item)
    cursor pointer
    width 22px
    padding 4px
    border-radius 4px
    &:hover
      background #e9e9e9
</style>
