<template>
  <div class="v-editor">
    <VMenu class="v-editor-head" />
    <div
      :id="'ved' + _uid"
      ref="editor"
      :class="['v-editor-body', `v-editor-body-${_uid}`]"
      :data-placeholder="placeholder"
      contenteditable
      :style="styles"
      @input="emitJSON"
    ></div>
  </div>
</template>

<script>
import VMenu from "./components/VMenu.vue";
import { renderRichText } from "./renderJSON";
import { toJSON } from "./toJSON";
import {
  IMAGE_EXCEED_SIZE_AS_ATTACHMENT,
  JSON_EXCEED_SIZE_AS_ATTACHMENT,
  MAX_AUDIO_SIZE,
  MAX_IMAGE_SIZE,
  MAX_JSON_SIZE,
} from "./constants";
import { pasteHandle } from "./clipboard";
import { answerPointRebuild } from "./components/answerPoint";
import timeMixin from "@/mixins/timeMixin";

export default {
  name: "VEditor",
  components: {
    VMenu,
  },
  mixins: [timeMixin],
  props: {
    placeholder: { type: String, default: "请输入..." },
    value: {
      type: [String, Object],
      // 要么为null，要么一定要遵循结构 body.sections[]
      // const EMPTY_RICH_TEXT
      default: () => {
        return { sections: [] };
      },
    },
    styles: { type: String, default: "" },
    folder: { type: String, default: "" },
    enableAnswerPoint: { type: Boolean, default: false },
    enableFormula: { type: Boolean, default: true },
    enableAudio: { type: Boolean, default: true },
    maxAudioSize: { type: Number, default: MAX_AUDIO_SIZE, required: false },
    maxImageSize: { type: Number, default: MAX_IMAGE_SIZE, required: false },
    imageExceedSizeAsAttachment: {
      type: Number,
      default: IMAGE_EXCEED_SIZE_AS_ATTACHMENT,
      required: false,
    },
    jsonExceedSizeAsAttachment: {
      type: Number,
      default: JSON_EXCEED_SIZE_AS_ATTACHMENT,
      required: false,
    },
    maxJsonSize: { type: Number, default: MAX_JSON_SIZE, required: false },
    emitType: {
      type: String,
      default: "json",
    },
  },
  data() {
    return {};
  },
  watch: {
    value(val, oldVal) {
      if (val !== oldVal) {
        if (this.$refs.editor !== document.activeElement) {
          this.initData();
        }
      }
    },
  },
  mounted() {
    this.initData();
    this.$refs.editor.addEventListener("paste", pasteHandle.bind(this));
    this.$refs.editor.addEventListener("wheel", this.wheelEventHandle);
    this.$refs.editor.addEventListener("click", this.clickEventHandle);
  },
  beforeDestroy() {
    this.clearSetTs();
  },
  methods: {
    initData() {
      if (this.emitType === "html") {
        this.$refs.editor.innerHTML = this.value;
      } else {
        const content = this.value || { sections: [] };
        renderRichText(content, this.$refs.editor, false);
      }
    },
    emitJSON($event) {
      if (!this.$refs.editor.contentEditable) {
        // 不是出于contentEditable则不更新
        return;
      }

      if (this.enableAnswerPoint) answerPointRebuild.bind(this)($event);

      if (this.emitType === "html") {
        const content = this.$refs.editor.innerHTML;
        this.$emit("input", content);
        this.$emit("change", content);
        return;
      }

      this.clearSetTs();
      // 延迟触发input任务，避免频繁触发，同时也等待图片渲染，方便获取图片显示尺寸
      this.addSetTime(() => {
        // console.log("input:" + Math.random());
        this.inputDelaying = false;
        const json = toJSON(this.$refs.editor);
        this.$emit("input", json);
        this.$emit("change", json);
        // this.$emit("on-result", json);
      }, 200);
    },
    wheelEventHandle(e) {
      // console.log(e);
      // console.dir(e.target);
      const el = e.target;
      if (el.tagName && el.tagName === "IMG") {
        e.preventDefault();
        e.stopPropagation();
        const shift = e.deltaY > 0;
        const newWidth =
          +getComputedStyle(el).width.replace("px", "") + (shift ? 1 : -1);
        // console.log(newWidth, el.naturalWidth);
        if (newWidth >= 16 && newWidth <= el.naturalWidth) {
          el.style.width = newWidth + "px";
          el.style.height =
            (newWidth / el.naturalWidth) * el.naturalHeight + "px";
          // el.setAttribute("width", newWidth);

          this.emitJSON();
        }
      }
    },
    clickEventHandle(e) {
      const el = e.target;
      if (el.tagName && el.tagName === "IMG") {
        e.preventDefault();
        e.stopPropagation();
        const selection = window.getSelection();
        selection.removeAllRanges();
        const range = document.createRange();
        range.selectNode(el);
        selection.addRange(range);
      }
    },
  },
};
</script>

<style>
.v-editor {
  position: relative;
  line-height: 20px;
}
.v-editor-head {
  position: absolute;
  left: 2px;
  right: 2px;
  background-color: #fff;
  top: 2px;
  z-index: 9;
  border-bottom: 1px solid #f0f0f0;
}

.v-editor-body,
.sourceView {
  border: 1px solid #e4e7ed;
  border-radius: 5px;
  min-height: 100px;
  max-height: 300px;
  padding: 8px;
  padding-top: 32px;
  overflow: scroll;
  outline: none;
  white-space: pre-wrap;
}

.sourceView {
  margin: -5px;
}

.v-editor-body[contenteditable="true"]:empty:not(:focus)::before {
  content: attr(data-placeholder);
  color: grey;
}
.v-editor-body:focus {
  border-color: #1886fe;
}

.v-editor-body div {
  min-height: 18px;
  line-height: 20px;
}

.v-editor-body img {
  max-width: 100%;
}
.v-editor-body img[data-is-answer-point] {
  max-height: 16px;
  display: inline-block;
  vertical-align: text-top;
  border-bottom: 1px solid #000;
}

.v-editor-body img.audio {
  height: 16px;
  padding: 0 2px;
  display: inline-block;
  margin-bottom: 4px;
}
.v-editor-body img[data-is-image] {
  /* max-height: 42px; */
  display: inline-block;
}

.v-editor-body audio {
  height: 16px;
  width: 180px;
  display: inline-block;
  margin-bottom: -4px;
}

.v-editor-body ::-webkit-media-controls-mute-button {
  display: none !important;
}

.v-editor-body ::-webkit-media-controls-volume-slider {
  display: none !important;
}

.v-editor-body b {
  font-weight: bold;
}
.v-editor-body i {
  font-style: italic;
}
.v-editor-body u {
  text-decoration: underline;
}
</style>
