<template>
  <div class="right-click-menu">
    <div
      ref="RightMenuBody"
      class="right-menu-body"
      :style="styles"
      v-clickoutside="close"
      v-if="visible"
    >
      <ul>
        <template v-if="!IS_NOT_TOPIC">
          <li @click="toEdit">
            <i class="el-icon-edit-outline"></i>
            {{ IS_CONTAINER_ELEMENT ? "编辑元素" : "编辑大题" }}
          </li>
          <li class="li-danger" @click="toDelete">
            <i class="el-icon-delete"></i>
            {{ IS_CONTAINER_ELEMENT ? "删除元素" : "删除大题" }}
          </li>
        </template>
        <li
          v-if="IS_CONTAINER_ELEMENT && (IS_EXPLAIN || IS_COMPOSITION)"
          @click="toCopyExplainElement"
        >
          <i class="el-icon-copy-document"></i> 复制元素
        </li>
        <li
          v-if="(IS_EXPLAIN || IS_COMPOSITION) && curCopyElement"
          @click="toPasteExplainElement"
        >
          <i class="el-icon-document-copy"></i> 粘贴元素
        </li>
        <template v-if="IS_EXPLAIN || IS_COMPOSITION">
          <li @click="toCopyChildren">
            <i class="el-icon-circle-plus-outline"></i> 新增答题区
          </li>
          <li
            class="li-danger"
            @click="toDeleteChildren"
            v-if="showDeleteChildBtn"
          >
            <i class="el-icon-delete"></i> 删除答题区
          </li>
        </template>
        <li v-if="CAN_MOVE_UP" @click="toMoveUpTopic">
          <i class="el-icon-upload2"></i> 上移大题
        </li>
        <li v-if="CAN_MOVE_DOWN" @click="toMoveDownTopic">
          <i class="el-icon-download"></i> 下移大题
        </li>
        <li v-if="!IS_CONTAINER_ELEMENT && !IS_NOT_TOPIC" @click="toInsetTopic">
          <i class="el-icon-add-location"></i> 插入大题
        </li>
        <li @click="toInsertForbidAnswer">
          <i class="el-icon-crop"></i> 插入禁答区
        </li>
        <li v-if="IS_NOT_TOPIC" class="li-danger" @click="toDelete">
          <i class="el-icon-delete"></i> 删除禁答区
        </li>
      </ul>
    </div>
  </div>
</template>

<script>
import { mapState, mapMutations, mapActions } from "vuex";
import { deepCopy } from "../plugins/utils";
import { fetchSameSerialNumberChildrenPositionInfo } from "../store/card";
import Clickoutside from "element-ui/src/utils/clickoutside";
import { getElementModel, EDITABLE_NOT_TOPIC } from "../elementModel";

export default {
  name: "right-click-menu",
  directives: { Clickoutside },
  data() {
    return {
      visible: false,
      showDeleteChildBtn: false,
      curCopyElement: null,
      styles: {
        position: "fixed",
        zIndex: 3000,
      },
    };
  },
  computed: {
    ...mapState("card", ["curElement", "topics", "topicSeries"]),
    IS_CONTAINER_ELEMENT() {
      return !!this.curElement.container;
    },
    IS_EXPLAIN() {
      return (
        this.curElement.type === "EXPLAIN" ||
        (this.curElement.container &&
          this.curElement.container.type === "EXPLAIN")
      );
    },
    IS_COMPOSITION() {
      return (
        this.curElement.type === "COMPOSITION" ||
        (this.curElement.container &&
          this.curElement.container.type === "COMPOSITION")
      );
    },
    CAN_MOVE_UP() {
      if (this.IS_CONTAINER_ELEMENT || this.IS_NOT_TOPIC) return false;

      const curTopicPos = this.topicSeries.findIndex(
        (item) => item.id === this.curElement.parent.id
      );

      return (
        curTopicPos &&
        this.topicSeries[curTopicPos - 1].sign ===
          this.topicSeries[curTopicPos].sign
      );
    },
    CAN_MOVE_DOWN() {
      if (this.IS_CONTAINER_ELEMENT || this.IS_NOT_TOPIC) return false;

      const curTopicPos = this.topicSeries.findIndex(
        (item) => item.id === this.curElement.parent.id
      );

      return (
        curTopicPos !== this.topicSeries.length - 1 &&
        this.topicSeries[curTopicPos + 1].sign ===
          this.topicSeries[curTopicPos].sign
      );
    },
    IS_NOT_TOPIC() {
      return EDITABLE_NOT_TOPIC.includes(this.curElement.type);
    },
  },
  mounted() {
    this.init();
  },
  methods: {
    ...mapMutations("card", ["setOpenElementEditDialog"]),
    ...mapActions("card", [
      "actElementById",
      "removeElement",
      "removeElementChild",
      "pasteExplainElementChild",
      "rebuildPages",
      "copyExplainChildren",
      "deleteExplainChildren",
      "topicMoveUp",
      "addForbidArea",
      "scrollToElementPage",
    ]),
    init() {
      // 注册自定义右键事件菜单
      document.oncontextmenu = function () {
        return false;
      };
      document.addEventListener("mouseup", this.docMouseUp);
    },
    close() {
      this.visible = false;
    },
    show() {
      this.visible = true;
    },
    docMouseUp(e) {
      if (e.button === 2) {
        this.rightClick(e);
      }
    },
    rightClick(e) {
      const id = this.getRelateElementId(e.target);
      if (!id) return;

      this.actElementById(id);
      let curElement = this.curElement;
      const TYPES = ["EXPLAIN", "COMPOSITION"];
      if (
        TYPES.includes(curElement.type) ||
        (curElement.container && TYPES.includes(curElement.container.type))
      ) {
        if (curElement.container) {
          const pos = this.topics.findIndex(
            (item) => item.id === curElement.container.id
          );
          curElement = this.topics[pos];
        }
        const positionInfos = fetchSameSerialNumberChildrenPositionInfo(
          curElement,
          this.topics
        );
        this.showDeleteChildBtn = positionInfos.length >= 2;
      }
      this.show();

      this.$nextTick(() => {
        const { x: clickLeft, y: clickTop } = e;
        const { offsetWidth: menuWidth, offsetHeight: menuHeight } =
          this.$refs.RightMenuBody;

        const { innerWidth: wWidth, innerHeight: wHeight } = window;

        let menuLeft = clickLeft,
          menuTop = clickTop;
        if (menuWidth + clickLeft > wWidth) {
          menuLeft = clickLeft - menuWidth;
        }
        if (menuHeight + clickTop > wHeight) {
          menuTop = clickTop - menuHeight;
        }

        this.styles = Object.assign({}, this.styles, {
          top: menuTop + "px",
          left: menuLeft + "px",
        });
      });
    },
    getRelateElementId(dom) {
      let parentNode = dom;
      while (
        !(
          (parentNode["id"] && parentNode["id"].includes("element-")) ||
          parentNode.className.includes("page-column-body")
        )
      ) {
        parentNode = parentNode.parentNode;
      }
      const elementType = parentNode.getAttribute("data-type");
      const unValidElement = ["TOPIC_HEAD", "CARD_HEAD"];

      return parentNode["id"] &&
        elementType &&
        !unValidElement.includes(elementType)
        ? parentNode["id"]
        : null;
    },
    toEdit() {
      this.curElement._edit = true;
      this.close();
      this.setOpenElementEditDialog(true);
    },
    toDelete() {
      this.close();

      if (this.IS_NOT_TOPIC) {
        this.removeSelectElement();
        return;
      }

      const name = this.IS_CONTAINER_ELEMENT ? "元素" : "大题";
      this.$confirm(`确定要删除当前${name}吗?`, "提示", {
        type: "warning",
      })
        .then(() => {
          this.removeSelectElement();
        })
        .catch(() => {});
    },
    toCopyChildren() {
      this.close();
      this.copyExplainChildren(this.curElement);
      this.toRebuildPages();
    },
    toDeleteChildren() {
      this.close();
      this.deleteExplainChildren(this.curElement);
      this.toRebuildPages();
    },
    removeSelectElement() {
      if (this.curElement["container"]) {
        this.removeElementChild(this.curElement);
      } else {
        this.removeElement(this.curElement);
      }

      this.toRebuildPages();
    },
    toCopyExplainElement() {
      this.close();
      this.curCopyElement = deepCopy(this.curElement);
    },
    toPasteExplainElement() {
      this.close();
      const id = this.curElement.container
        ? this.curElement.container.id
        : this.curElement.id;
      const pasteElement =
        this.curCopyElement.container.id === id
          ? Object.assign({}, this.curCopyElement, {
              y: this.curCopyElement.y + 20,
            })
          : this.curCopyElement;

      this.pasteExplainElementChild({
        curElement: this.curElement,
        pasteElement,
      });
      this.toRebuildPages();
    },
    toMoveUpTopic() {
      this.close();
      this.topicMoveUp(this.curElement.parent.id);
      this.toRebuildPages();
    },
    toMoveDownTopic() {
      this.close();
      const curTopicPos = this.topicSeries.findIndex(
        (item) => item.id === this.curElement.parent.id
      );
      this.topicMoveUp(this.topicSeries[curTopicPos + 1].id);
      this.toRebuildPages();
    },
    toInsetTopic() {
      this.close();
      this.$emit("inset-topic", {
        id: this.curElement.parent.id,
        type: this.curElement.type,
      });
    },
    toInsertForbidAnswer() {
      this.close();
      let element = getElementModel("FORBID_AREA");
      element.w = document.getElementById("topic-column").offsetWidth;
      element.sign = this.curElement.sign;
      this.addForbidArea({ element, beforeElementId: this.curElement.id });

      this.$nextTick(() => {
        this.rebuildPages();
        this.$nextTick(() => {
          this.scrollToElementPage(element);
        });
      });
    },
    toRebuildPages() {
      this.$nextTick(() => {
        this.rebuildPages();
      });
    },
  },
  beforeDestroy() {
    document.oncontextmenu = null;
    document.removeEventListener("mouseup", this.docMouseUp);
  },
};
</script>
