<!--
 * @FileDescription: 评论输入框
 * @Date: 2023-06-06
 * @LastEditTime: 2023-06-06
-->
<script setup lang="ts">
import { ref, reactive, nextTick } from 'vue';

const inputRef = ref<any>(null);
const showEmoji = ref(false);

const emojiList = [
  {
    title: '分组1',
    children: [
      {
        name: 'strawberry',
        label: '草莓',
        url: require('./emojis/strawberry.png'),
      },
      {
        name: 'watermelon',
        label: '西瓜',
        url: require('./emojis/watermelon.png'),
      },
    ],
  },
  {
    title: '分组2',
    children: [
      {
        name: 'kiss',
        label: '亲亲',
        url: require('./emojis/kiss.png'),
      },
      {
        name: 'se',
        label: '色',
        url: require('./emojis/se.png'),
      },
      {
        name: 'angel',
        label: '天使',
        url: require('./emojis/angel.png'),
      },
      {
        name: 'reserved',
        label: '矜持',
        url: require('./emojis/reserved.png'),
      },
      {
        name: 'smile',
        label: '微笑',
        url: require('./emojis/smile.png'),
      },
      {
        name: 'oh',
        label: '哦',
        url: require('./emojis/oh.png'),
      },
    ],
  },
  {
    title: '应用',
    children: [
      {
        name: 'QQ',
        label: 'QQ',
        url: require('./emojis/QQ.png'),
      },
      {
        name: 'WeChat',
        label: '微信',
        url: require('./emojis/WeChat.png'),
      },
    ],
  },
];
const state = reactive({
  commentContent: '',
  commentContentByUI: '',
  canClickIcon: false,
});

function willShow() {
  showEmoji.value = !showEmoji.value;
}

// 点击表情
function clikeEmoji(item: any) {
  // 编辑框设置焦点
  const inputDom = inputRef.value;
  inputDom.focus();

  const selection = document.getSelection() as Selection;
  const rangeCount = selection.rangeCount;
  if (rangeCount > 0) {
    // 设置最后光标对象
    let range = selection.getRangeAt(0);
    range.deleteContents(); // 从 Document 中移除 Range 内容

    // 创建标签
    const img = document.createElement('img');
    img.setAttribute('class', 'input-img');
    img.src = item.url;
    img.alt = item.label;
    img.style.height = '20px';
    img.style.width = '20px';
    img.style.transform = 'translateY(5px)';

    // 在 Range 开头插入一个节点
    range.insertNode(img);
    range = range.cloneRange();
    range.setStartAfter(img);

    range.collapse(true);
    selection.removeAllRanges();
    selection.addRange(range);
  }
  showEmoji.value = false;
}

// 发表评论
function sendComment() {
  const re = formatWord(getDomValue(inputRef.value));
  state.commentContent = re;
  const strlist = textJoin(re, []);
  // console.log('NB', strlist);
  const div = document.createElement('div');
  div.style.lineHeight = '22px';
  for (const ite of strlist) {
    if (ite.isHtml) {
      div.appendChild(ite.html);
    } else {
      const list = lineFeed(ite.text, []);
      for (const n of list) {
        if (n.isHtml) {
          div.appendChild(n.html);
        } else {
          const node = document.createTextNode(n.text);
          div.appendChild(node);
        }
      }
    }
  }
  nextTick(() => {
    const outHtml = div.outerHTML;
    state.commentContentByUI = outHtml;
  });
}

function textJoin(str: string, resArr: any[]) {
  const startIndex = str.indexOf('[');
  if (startIndex > -1) {
    let afterStr = str.substring(startIndex + 1);
    let endIndex = afterStr.indexOf(']');
    if (endIndex > -1) {
      const imgKey = afterStr.substring(0, endIndex);
      const imgData = findImg(imgKey);
      if (imgData) {
        const img = document.createElement('img');
        img.setAttribute('class', 'input-img');
        img.src = imgData.url;
        img.alt = imgData.label;
        img.style.height = '26px';
        img.style.width = '26px';
        img.style.transform = 'translateY(5px)';

        resArr.push({
          text: str.substring(0, startIndex),
          isHtml: false,
        });
        resArr.push({
          html: img,
          isHtml: true,
        });
        textJoin(afterStr.substring(endIndex + 1), resArr);
      } else {
        resArr.push({
          text: str.substring(0, endIndex + 1),
          isHtml: false,
        });
        textJoin(str.substring(endIndex + 1), resArr);
      }
    } else {
      resArr.push({
        text: str,
        isHtml: false,
      });
    }
  } else {
    resArr.push({
      text: str,
      isHtml: false,
    });
  }

  return resArr;
}

function findImg(imgk: string) {
  let data = null as any;

  let imgLsit = [] as any[];
  for (const i of emojiList) {
    imgLsit.push(...i.children);
  }

  for (const i of imgLsit) {
    if (i.label === imgk) {
      data = i;
      break;
    }
  }
  return data;
}

function inputFocus() {
  // console.log('111');
  state.canClickIcon = true;
}
function inputBlur() {
  // state.canClickIcon = false;
}
// 获取纯文本内容
function getDomValue(elem: any) {
  let res = '';
  Array.from(elem.childNodes).forEach((child: any) => {
    if (child.nodeName === '#text') {
      res += child.nodeValue;
    } else if (child.nodeName === 'BR') {
      // res += '\n';
      res += '<br>';
    } else if (child.nodeName === 'BUTTON') {
      res += getDomValue(child);
    } else if (child.nodeName === 'IMG') {
      res += '[' + child.alt + ']';
    } else if (child.nodeName === 'DIV') {
      // res += '\n' + getDomValue(child);
      res += '<br>' + getDomValue(child);
    }
  });
  return res;
}
// 换行标签转换
function lineFeed(val: string, arr: any[]) {
  const index = val.indexOf('<br>');
  if (index > -1) {
    const br = document.createElement('br');
    arr.push({
      isHtml: false,
      text: val.substring(0, index),
    });
    arr.push({
      isHtml: true,
      html: br,
    });
    lineFeed(val.substring(index + 4), arr);
  } else {
    arr.push({
      isHtml: false,
      text: val,
    });
  }

  return arr;
}
// 文本换行
function formatWord(str: string) {
  return str.replace(/\\n/g, '<br>');
}
</script>
<template>
  <div class="column justify-center items-center container-height">
    <div style="width: 460px">
      <div class="avatar-box">
        <q-avatar size="38px">
          <img src="https://cdn.quasar.dev/img/avatar.png" />
        </q-avatar>
        <span class="name">皮皮虾</span>
      </div>
      <div class="input-box">
        <div
          class="input-sty"
          contenteditable="true"
          ref="inputRef"
          placeholder="输入评论"
          @focus="inputFocus"
          @blur="inputBlur"
        ></div>
        <div class="operation">
          <div class="icon-box">
            <q-icon
              name="mood"
              class="_icon"
              size="22px"
              @click="willShow"
              v-if="state.canClickIcon"
            />
            <div class="emoji-box-fa" v-show="showEmoji" id="_emoji">
              <div class="emoji-box">
                <div class="group-item" v-for="i in emojiList" :key="i.title">
                  <div class="group-item-title">{{ i.title }}</div>
                  <div class="childre-box">
                    <div
                      class="item-box"
                      v-for="chi in i.children"
                      :key="chi.name"
                      :title="chi.label"
                      @click="clikeEmoji(chi)"
                    >
                      <img :src="chi.url" :alt="chi.label" />
                    </div>
                  </div>
                </div>
              </div>
            </div>
          </div>
          <q-btn
            unelevated
            color="primary"
            label="发表评论"
            @click="sendComment"
          />
        </div>
      </div>
    </div>
    <div style="width: 460px">
      <div>评论内容:</div>
      <div v-html="state.commentContentByUI" class="comment-sty"></div>
      <div class="q-mt-lg">评论内容:</div>
      <div>{{ state.commentContent }}</div>
    </div>
  </div>
</template>

<style lang="scss" scoped>
.input-sty {
  min-width: 200px;
  min-height: 80px;
  font-size: 14px;
  line-height: 22px;
  padding: 5px 8px;
  border: 1px solid #ddd;
  color: $gray-text;

  border-radius: 0.25rem;
  transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
  // transform: translateY(-10px) scale(0.9);

  &:empty::before {
    content: attr(placeholder);
    color: $gray-light-text;
  }
  &:focus {
    color: #212529;
    background-color: #fff;
    outline: 0;
    border-color: $primary;
    box-shadow: 0 0 0 0.25rem $primary-focus-shadow;
  }
}
.name {
  color: rgba(0, 0, 0, 0.55);
  padding-left: 6px;
}
.avatar-box {
  margin-bottom: 4px;
}
.input-box {
  margin-left: 40px;
}
.operation {
  padding: 6px 0;
  display: flex;
  flex-direction: row;
  justify-content: space-between;
}
.icon-box {
  position: relative;
  color: rgba(0, 0, 0, 0.55);
  ._icon {
    color: inherit;
    &:hover {
      cursor: pointer;
      color: $primary;
    }
  }
  .emoji-box-fa {
    position: absolute;
    padding: 8px;
    border-radius: 6px;
    top: 26px;
    left: 0;
    width: 400px;
    height: 200px;
    z-index: 10;
    background: #fff;
    box-shadow: rgba(0, 0, 0, 0.1) 0px 4px 12px;
  }
  .emoji-box {
    width: 100%;
    height: 100%;
    overflow: auto;
    color: black;

    &:hover {
      cursor: default;
    }
    .group-item-title {
      font-size: 12px;
      color: $gray-text;
    }
    .childre-box {
      display: flex;
      flex-direction: row;
      flex-wrap: wrap;
    }

    .item-box {
      width: 40px;
      height: 40px;
      box-sizing: border-box;
      transition: all 0.25s;
      > img {
        width: 100%;
        height: 100%;
      }
      &:hover {
        cursor: pointer;
        transform: scale(1.2);
      }
    }
  }
}
.img {
  width: 40px;
  height: 40px;
}
.comment-sty {
  min-height: 80px;
  background: rgba(0, 0, 0, 0.05);
  border-radius: 0.25rem;
  padding: 5px 8px;
  color: $gray-text;
}
</style>