<template>
  <div class="home">
    <a-layout
      id="components-layout-demo-top-side-2"
      :style="{
        overflow: 'auto',
        width: '100%',
        height: '100vh',
        position: 'fixed',
        left: 0,
      }"
    >
      <!-- 头部 -->
      <a-layout-header class="header" style="text-align: left">
        <a-row :gutter="24">
          <a-col :span="6">
            <a-dropdown
              v-for="item of headMenu"
              :key="item.type"
              style="margin-right: 10px"
            >
              <a-button ghost>{{ item.name }}<a-icon type="down" /></a-button>
              <a-menu slot="overlay" :mode="'vertical'">
                <a-menu-item
                  v-for="it of item.children"
                  :key="it.show"
                  @click="operationFile(item.type, it.type)"
                >
                  {{ it.name }}
                </a-menu-item>
              </a-menu>
            </a-dropdown>
          </a-col>
          <a-col :span="14">
            <div style="color: #fff">
              <a-button type="dashed" ghost @click="preview"> 预览 </a-button>
              <a-divider type="vertical" />
              <span
                >视图：<a-input-number
                  v-model="scalecom"
                  :min="30"
                  :max="500"
                  :formatter="(value) => `${value}%`"
              /></span>
              <a-divider type="vertical" />
              <a-popover>
                <template slot="content">
                  <a-input-number v-model="lineWidthcom" :min="1" />
                </template>
                <span>线宽：{{ lineWidthcom }}</span>
              </a-popover>
              <a-divider type="vertical" />
              <a-tooltip>
                <template slot="title">
                  <p v-if="locked < 1">未锁定</p>
                  <p v-else>已锁定</p>
                </template>
                <a-icon
                  :type="locked < 1 ? 'unlock' : 'lock'"
                  @click="lockClick()"
                />
              </a-tooltip>
              <a-divider type="vertical" />
              <a-select
                style="width: 20%"
                v-model="lineName"
                @change="handlLineName"
              >
                <a-select-option
                  v-for="item of lineList"
                  :key="item.type"
                  :value="item.type"
                >
                  <span>{{ item.name }} </span>
                  <span style="float: right"
                    ><i
                      style="font-size: 2vh"
                      :class="`t-icon t-${item.type}`"
                    ></i>
                  </span>
                </a-select-option>
              </a-select>
              <a-divider type="vertical" />
              <a-select
                style="width: 15%"
                v-model="fromArrow"
                @change="handleFromArrowType"
              >
                <a-select-option
                  v-for="item of arrowTypes"
                  :key="item"
                  :value="item"
                >
                  <i style="font-size: 35px" :class="`t-icon t-to-${item}`"></i>
                  <!-- style="font-size: 7vh" -->
                </a-select-option>
              </a-select>
              <a-divider type="vertical" />
              <a-select
                style="width: 15%"
                v-model="toArrow"
                @change="handleToArrowType"
              >
                <a-select-option
                  v-for="item of arrowTypes"
                  :key="item"
                  :value="item"
                >
                  <i style="font-size: 35px" :class="`t-icon t-to-${item}`"></i>
                </a-select-option>
              </a-select>
            </div>
          </a-col>
          <a-col :span="4">
            <div style="text-align: right">
              <a-button ghost @click="saveTopology" style="margin-right: 2vh">
                保存
              </a-button>
              <a-button ghost @click="back" type="dashed"> 返回 </a-button>
            </div>
          </a-col>
        </a-row>
      </a-layout-header>
      <a-layout>
        <!-- 左侧栏 -->
        <a-layout-sider
          width="200"
          style="background: #fff; overflow: hidden; height: 95vh"
        >
          <div>
            <a-tabs default-active-key="1" size="small">
              <a-tab-pane key="1" tab="系统组件">
                <div class="div-scoll">
                  <a-collapse>
                    <a-collapse-panel
                      v-for="(item, index) in tools"
                      :key="index"
                      :header="item.group"
                    >
                      <a-row style="padding: 0px">
                        <a-card-grid
                          v-for="(btn, i) in item.children"
                          :key="i"
                          :title="btn.name"
                          :draggable="btn.data"
                          @dragstart="onDrag($event, btn, false)"
                          class="ant-card-grid"
                          :style="customStyle"
                        >
                          <i style="font-size: 25px" :class="`iconfont ${btn.icon}`"></i>
                        </a-card-grid>
                      </a-row>
                    </a-collapse-panel>
                    <a-collapse-panel
                      v-for="(item, index) in toolSvgs"
                      :key="index"
                      :header="item.group"
                    >
                      <a-row style="padding: 0px">
                        <a-card-grid
                          v-for="(btn, i) in item.children"
                          :key="i"
                          :title="btn.name"
                          :draggable="btn.data"
                          @dragover="allowDrop($event)"
                          @dragstart="onDrag($event, btn, true)"
                          class="ant-card-grid"
                          :style="customStyle"
                          v-html="btn.image"
                        >
                        </a-card-grid>
                      </a-row>
                    </a-collapse-panel>
                  </a-collapse>
                </div>
              </a-tab-pane>
              <!-- <a-tab-pane key="2" tab="我的组件">
                Content of Tab Pane 2
              </a-tab-pane>
              <a-tab-pane key="3" tab="我的图片">
                Content of Tab Pane 3
              </a-tab-pane> -->
            </a-tabs>
          </div>
        </a-layout-sider>
        <a-layout>
          <div style="position: relative; overflow: hidden">
            <div id="topology-hrhx" class="canvas"></div>
          </div>
        </a-layout>
        <a-layout-sider
          width="240"
          style="background: #fff; overflow: hidden; height: 95vh"
        >
          <div>
            <space-view
              v-if="opt == 'space'"
              :canvas="canvas.data"
              @ok="uploadCanvasData"
            ></space-view>
            <node-view
              v-if="opt == 'addNode' || opt == 'node'"
              :node.sync="node"
              @ok="updateProps"
            ></node-view>
            <line-view
              v-if="opt == 'addLine' || opt == 'line'"
              :line.sync="lineData"
              @ok="updateLines"
            ></line-view>
            <pens-view
              v-if="opt == 'multi'"
              :pens.sync="pens"
              @no="updateAlignNodes"
              @ok="updatePens"
              @spaceB="updateSpaceBetween"
              @updateSub="updatePensSubclass"
            ></pens-view>
          </div>
        </a-layout-sider>
      </a-layout>
    </a-layout>
    <!-- <recent-file ref="recent"></recent-file> -->
  </div>
</template>

<script>
import { Topology, Point } from "@topology/core";
// 图形库
import { register as registerFlow } from "@topology/flow-diagram";
import { register as registerActivity } from "@topology/activity-diagram";
import { register as registerClass } from "@topology/class-diagram";
import { register as registerSequence } from "@topology/sequence-diagram";
import {
  register as registerChart,
  echartsObjs,
} from "@topology/chart-diagram";
import { layout, alignNodes, spaceBetween } from "@topology/layout";
import {
  headMenu,
  lineList,
  arrowTypes,
} from "@/utils/topology/topologysetting.js";
import { getDatas } from "@/utils/topology/registerIconssetting.js";
import * as FileSaver from "file-saver";
import SpaceView from "@/components/topology/SpaceView.vue";
import NodeView from "@/components/topology/NodeView.vue";
import LineView from "@/components/topology/LineView.vue";
import PensView from "@/components/topology/PensView.vue";
import { assemble, assembleSvg } from "@/utils/topology/setting.js";
import { registerIcons, registerSvgs } from "@/utils/topology/customgraph.js";
import { getTopologyId, save } from "@/api/topology.js";
registerIcons();
registerSvgs();
export default {
  name: "TopologyWorkspace",
  components: {
    SpaceView,
    NodeView,
    LineView,
    PensView,
  },
  props: {
    backUrl: {
      type: String,
      default: "/",
    },
    previewUrl: {
      type: String,
      default: "/toplogyView/preview",
    },
  },
  data() {
    return {
      lineList,
      collapsed: false,
      canvas: "",
      lineName: "curve",
      fromArrow: "triangleSolid",
      toArrow: "triangleSolid",
      node: {},
      lineData: {},
      pens: [],
      arrowTypes,
      customStyle:
        "background: #fff;border-radius: 4px;margin-right:2%;margin-bottom: 15px;border: 0;overflow: hidden",
      headMenu,
      tools: [],
      toolSvgs: [],
      //组态相应默认配置
      scale: 100,
      locked: 0,
      opt: "space",
      lineWidth: 1,
      topologyData: {},
      topologyId: "",
      event: {
        name: "",
        data: null,
      },
    };
  },
  created() {
    registerFlow();
    registerActivity();
    registerClass();
    registerSequence();
    registerChart();
    this.tools = assemble();
    // this.toolSvgs = assembleSvg();
    this.registerIcons();
  },
  mounted() {
    document.addEventListener("keydown", this.saveContent);
    this.init();
  },
  destroyed() {
    document.removeEventListener("keydown", this.saveContent);
    this.canvas.destroy();
  },
  computed: {
    scalecom: {
      get() {
        return Math.round(this.scale * 100);
      },
      set(val) {
        this.scale = val / 100;
        this.canvas.scaleTo(val / 100);
      },
    },
    lineWidthcom: {
      get() {
        return this.lineWidth;
      },
      set(val) {
        this.lineWidth = val;
        this.canvas.data.lineWidth = val;
      },
    },
  },
  watch: {
    $route(val) {
      this.open();
    },
  },
  methods: {
    allowDrop(event) {
      event.preventDefault();
    },
    back() {
      this.$router.go(-1);
    },
    saveContent(e) {
      var key = window.event.keyCode
        ? window.event.keyCode
        : window.event.which;
      if (key === 83 && e.ctrlKey) {
        this.saveTopology();
        e.preventDefault();
      }
    },
    registerIcons() {
      for (let i of getDatas()) {
        this.tools.push(i);
      }
    },
    handlLineName(val) {
      this.canvas.data.lineName = val;
    },
    handleFromArrowType(val) {
      this.canvas.data.fromArrow = val;
    },
    handleToArrowType(val) {
      this.canvas.data.toArrow = val;
    },
    lockClick() {
      if (this.locked > 0) {
        this.locked = 0;
        this.canvas.lock(0);
      } else {
        this.canvas.lock(1);
        this.locked = 1;
      }
    },
    //文件及编辑
    operationFile(type, name) {
      switch (type) {
        case 1:
          if (name === "add") {
            this.$router.push({
              path: this.$route.path,
            });
            this.topologyData = {};
            this.canvas.open(this.topologyData);
            this.canvas.render();
          }
          if (name === "open") {
            this.handle_replace();
          }
          if (name === "import") {
            this.handle_replace();
          }
          if (name === "json") {
            this.handle_saveJson();
          }
          if (name === "png") {
            this.handle_savePng();
          }
          if (name === "svg") {
            this.handle_saveSvg();
          }
          if (name === "lately") {
          }
          break;
        case 2:
          if (name === "revoke") {
            this.canvas.undo();
          } else if (name === "shear") {
            this.canvas.cut();
          } else if (name === "copy") {
            this.canvas.copy();
          } else if (name === "paste") {
            this.canvas.paste();
          }
          break;
        default:
          console.log("暂无方法，请执行填写");
          break;
      }
    },
    //预览
    preview() {
      this.topologyData = JSON.parse(JSON.stringify(this.canvas.data));
      if (!this.$route.query.id) {
        this.$message.warning("未保存数据");
        return;
      }
      this.$router.push({
        path: this.previewUrl,
        query: {
          id: this.$route.query.id,
        },
      });
    },
    async open() {
      if (this.$route.query.id) {
        await getTopologyId(this.$route.query.id)
          .then((res) => {
            if (res.code === 200) {
              this.topologyData = res.data.data;
            }
          })
          .catch((res) => {
            this.topologyData = {};
          });
      }
      if (this.topologyData) {
        this.canvas.open(this.topologyData);
        this.canvas.render();
        this.toArrow = this.canvas.data.toArrow;
        this.fromArrow = this.canvas.data.fromArrow;
        this.lineName = this.canvas.data.lineName;
        this.canvas.lock(0);
        this.canvas.closeSocket()
        this.canvas.closeMqtt()
      }
    },
    init() {
      // 2. 创建画布
      // 其中，第一个参数'topo-canvas'表示canvas所在的父dom元素id，通常为<div class="canvas" id="topo-canvas"></div>；
      // 第二个参数{}表示画布选项，这里表示全部使用默认值。具体选项请参考后面的api文档。
      this.canvas = new Topology("topology-hrhx", {
        rotateCursor: "./rotate.cur",
        on: (event, data) => {
          this.optionsSet(event, data, this.canvas);
        },
      });
      // this.onSvgICON();
      // 3. 渲染图形
      // 画布图形数据，可以来自于官网下载的json
      this.open();
    },
    //处理svg图标
    onSvgICON() {
      window.Point = Point;
      if (window.registerTools) {
        window.registerTools(svgData);
      }
    },
    onDrag(event, node, it) {
      // console.log(event,node,it)
      if (it) {
        event.dataTransfer.setData(
          "Text",
          JSON.stringify({
            name: node.fullname,
            rect: {
              width: 100,
              height: 100,
            },
          })
        );
      } else {
        // if(node.data.name=="echarts"){
        //   node.removeFromDiv();
        // }
        // console.log(node.data.icon.charCodeAt().toString(16))
        event.dataTransfer.setData("Text", JSON.stringify(node.data));
      }
    },

    handle_replace() {
      const input = document.createElement("input");
      input.type = "file";
      input.onchange = (event) => {
        const elem = event.srcElement || event.target;
        if (elem.files && elem.files[0]) {
          const name = elem.files[0].name.replace(".json", "");
          const reader = new FileReader();
          reader.readAsText(elem.files[0]);
        }
      };
      input.click();
    },
    handle_saveJson() {
      if (!!this.canvas.data.name) {
        FileSaver.saveAs(
          new Blob([JSON.stringify(this.canvas.data)], {
            type: "text/plain;charset=utf-8",
          }),
          this.canvas.data.name + ".json"
        );
      } else {
        this.$notification.warn({
          message: "请填写图文名称",
        });
      }
    },

    handle_savePng() {
      if (!!this.canvas.data.name) {
        this.canvas.saveAsImage(this.canvas.data.name + ".png");
      } else {
        this.$notification.warn({
          message: "请填写图文名称",
        });
      }
    },

    handle_saveSvg() {
      let name = "";
      if (!!this.canvas.data.name) {
        name = this.canvas.data.name + ".svg";
      } else {
        this.$notification.warn({
          message: "请填写图文名称",
        });
        return;
      }
      const ctx = new C2S(
        this.canvas.canvas.width + 200,
        this.canvas.canvas.height + 200
      );
      for (const item of this.canvas.data.pens) {
        item.render(ctx);
      }
      let mySerializedSVG = ctx.getSerializedSvg();
      mySerializedSVG = mySerializedSVG.replace(
        "<defs/>",
        `<defs>
    <style type="text/css">
      @font-face {
        font-family: 'topology';
        src: url('http://at.alicdn.com/t/font_1331132_h688rvffmbc.ttf?t=1569311680797') format('truetype');
      }
    </style>
  </defs>`
      );

      mySerializedSVG = mySerializedSVG.replace(/--le5le--/g, "&#x");

      const urlObject = window.URL || window;
      const export_blob = new Blob([mySerializedSVG]);
      const url = urlObject.createObjectURL(export_blob);

      const a = document.createElement("a");

      a.setAttribute("download", name);
      a.setAttribute("href", url);
      const evt = document.createEvent("MouseEvents");
      evt.initEvent("click", true, true);
      a.dispatchEvent(evt);
    },
    updateProps(node) {
      this.canvas.updateProps(this.canvas.data.pens);
    },
    updateLines(line) {
      this.canvas.updateProps(this.canvas.data.pens);
    },
    uploadCanvasData(data) {
      this.canvas.open(data);
      this.canvas.render();
    },
    updatePens(params) {
      layout(this.pens, params);
      this.canvas.updateProps(this.canvas.data.pens);
    },
    updatePensSubclass(name, val) {
      for (let item of this.pens) {
        item[name] = val;
      }
      this.canvas.updateProps(this.canvas.data.pens);
    },
    updateAlignNodes(rect, align) {
      alignNodes(this.pens, rect, align);
      this.canvas.updateProps(this.canvas.data.pens);
    },
    updateSpaceBetween(params) {
      spaceBetween(this.pens, params.maxWidth);
      this.canvas.updateProps(this.canvas.data.pens);
    },
    async saveTopology() {
      let params = {};
      if (!!this.$route.query.id) {
        params.id = this.$route.query.id;
      }
      if (!this.canvas.data.name) {
        this.$message.error("请填写图文名称");
        return;
      }
      params.name = this.canvas.data.name;
      params.data = this.canvas.data;
      await save(params)
        .then((res) => {
          if (res.code === 200) {
            this.$message.success("保存成功");
            this.$router.push({
              path: this.$route.path,
              query: {
                id: res.data.id,
              },
            });
          }
        })
        .catch((res) => {
          this.$route.query.id = "";
        });
    },
    optionsSet(event, data, canvas) {
      switch (event) {
        case "scale":
          this.scale = data;
          break;
        case "locked":
          this.locked = data;
          this.opt = "space";
          break;
        case "space":
          this.opt = event;
          break;
        case "node":
          this.opt = event;
          this.node = data;
        case "addNode":
          this.opt = event;
          this.node = data;
        case "addLine":
          this.opt = event;
          this.lineData = data;
          break;
        case "line":
          this.opt = event;
          this.lineData = data;
          break;
        case "multi":
          this.opt = event;
          this.pens = data;
          break;
        case "delete":
          this.opt = "space";
          break;
      }
    },
  },
};
</script>
<style  lang="scss">
aside {
  padding: 0px 0px;
  margin-bottom: 20px;
  border-radius: 2px;
  line-height: 32px;
  font-size: 16px;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen,
    Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif;
  color: hsl(210deg 29% 24%);
  -webkit-font-smoothing: antialiased;
}
.home {
  width: 100%;
  height: 100%;
}
.canvas {
  height: 100vh;
  width: 100%;
}
::-webkit-scrollbar {
  width: 5px;
  height: 5px;
  background-color: #fff;
}
/*定义滚动条轨道 内阴影*/
::-webkit-scrollbar-track {
  box-shadow: inset 0 0 6px rgba(0, 0, 0, 0);
  background-color: #ccc;
}
/*定义滑块 内阴影*/
::-webkit-scrollbar-thumb {
  box-shadow: inset 0 0 6px rgba(0, 0, 0, 0);
  background-color: #726868;
  border-radius: 10px;
}
.ant-form-item {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
  color: #000;
  // font-size: 14px;
  font-variant: tabular-nums;
  line-height: 1.5;
  list-style: none;
  font-feature-settings: "tnum";
  margin-bottom: 5px;
  vertical-align: top;
}

.ant-input-group {
  line-height: 0.5;
}
.ant-divider-horizontal {
  display: block;
  clear: both;
  width: 100%;
  min-width: 100%;
  height: 1px;
  margin: 12px 0;
}
.full {
  flex: 1;
  width: initial;
  position: relative;
  overflow: auto;
  background: #fff;
}
.ant-layout-header {
  height: 45px;
  padding: 0 50px;
  line-height: 45px;
  background: hsl(209deg 100% 55%);
}
.ant-collapse {
  background-color: rgb(255, 255, 255);
  .ant-collapse-item {
    .ant-collapse-header {
      color: #000;
    }
  }
}
.ant-tabs {
  .ant-tabs-small-bar {
    .ant-tabs-tab {
      padding: 10px 5px;
      margin: 0px 3px 0 0;
      font-size: 13px;
    }
  }
}
.ant-collapse {
  .ant-collapse-item {
    .ant-collapse-header {
      line-height: 8px;
      font-size: 10px;
    }
  }
}
.ant-tabs-bar {
  margin: 0 0 3px 0;
}
.ant-card-grid {
  padding: 0px;
  width: 23%;
  text-align: center;
}
.ant-layout-sider-children {
  border: 1px solid #c4c4c4;
  border-radius: 5px;
  height: 100%;
  margin-top: -0.1px;
  padding-top: 0.1px;
}
.div-scoll {
  width: 100%;
  height: 90vh;
  overflow-x: hidden;
  overflow-y: scroll;
}
</style>