<template >
  <div class="vueFlow1">
    <div id="container"></div>
    <div id="stencil"></div>
    <div id="graph-container"></div>
    <div id="minimap"></div>
  </div>
  <el-dialog title="节点信息配置" v-model="dialogVisible" width="500" v-if="dialogVisible">
    <byForm :formConfig="formConfig" :formOption="formOption" v-model="formData.data" v-loading="loading" :rules="rules" ref="byform">
    </byForm>
    <template #footer>
      <div>
        <el-button @click="dialogVisible = false" size="default">取 消</el-button>
        <el-button type="danger" @click="deleteFlowDefinitionNodeObj()" size="default">
          删 除
        </el-button>
        <el-button type="primary" @click="submitForm" size="default">
          确 定
        </el-button>
      </div>
    </template>
  </el-dialog>
</template>
<script lang="ts" setup>
import {
  defineComponent,
  ref,
  onMounted,
  onUnmounted,
  watch,
  reactive,
  toRefs,
  computed,
  nextTick,
  getCurrentInstance,
  onDeactivated,
  onActivated,
} from "vue";
import byForm from "@/components/byForm/index";
import { Graph, Shape } from "@antv/x6";
import { Stencil } from "@antv/x6-plugin-stencil";
import { Transform } from "@antv/x6-plugin-transform";
import { Selection } from "@antv/x6-plugin-selection";
import { Snapline } from "@antv/x6-plugin-snapline";
import { Keyboard } from "@antv/x6-plugin-keyboard";
import { Clipboard } from "@antv/x6-plugin-clipboard";
import { register } from "@antv/x6-vue-shape";
import { History } from "@antv/x6-plugin-history";
import Cookies from "js-cookie";
import { ElMessage, ElMessageBox } from "element-plus";
import startBtn from "./startBtn.vue";
import endBtn from "./endBtn.vue";
import handleBtn from "./handleBtn.vue";
import branchBtn from "./branchBtn.vue";
import { MiniMap } from "@antv/x6-plugin-minimap";
import useTagsViewStore from "@/store/modules/tagsView";
import { rectToBox } from "@vue-flow/core/dist/utils/graph";
import { async } from "@antv/x6/lib/registry/marker/main";
defineProps({
  title: {
    type: Object,
    default: "",
  },
  nodeObject: {
    type: String,
    default: "",
  },
});
const { proxy } = getCurrentInstance();
const flowNodeObj = ref({});
const dialogVisible = ref(false);
const loading = ref(false);
const byform = ref(null);
const formData = reactive({
  data: {},
});
const formOption = reactive({
  inline: true,
  labelWidth: 100,
  itemWidth: 100,
});
const formConfig = computed(() => {
  return [
    {
      type: "input",
      prop: "nodeName",
      label: "工序名称",
      required: true,
      itemType: "text",
    },
  ];
});
const rules = reactive({
  nodeName: [
    {
      required: true,
      message: "请输入工序名称",
      trigger: "blur",
    },
  ],
});
const flowDefinitionNodeObj = ref({});
let graph;
const submitFormData = {
  flowInfoId: null,
  titleTemplate: null,
  tenantId: Cookies.get("tenantId"),
  nodeObject: "",
  lineObject: "",
  flowDefinitionNodeList: [],
};

const deleteFlowDefinitionNodeObj = () => {
  graph.removeNode(formData.data.id);
  delete flowNodeObj.value[formData.data.id];
  dialogVisible.value = false;
  // let productionId = formData.data.cell.store.data.productionId;
  // type 1为自定义工序 0为固定工序
  // proxy.$emit("removeRow", { id: productionId });
};

const submitForm = () => {
  byform.value.handleSubmit((valid) => {
    console.log(formData.data.nodeName, "sada");

    formData.data.cell.setData({
      title: formData.data.nodeName,
    });
    flowNodeObj.value[formData.data.id].nodeName = formData.data.nodeName;
    dialogVisible.value = false;
    // let cell = formData.data.cell;
    // let productionId = cell.store.data.productionId;
    // let name = cell.store.data.data.title;
    // proxy.$emit("changeName", { productionId, name });
  });
};

const submitAll = () => {
  const nodeList = graph.toJSON().cells;
  submitFormData.nodeObject = JSON.stringify(nodeList);
  // submitFormData.lineObject = JSON.stringify(flowDefinitionNodeObj.value);
  console.log(nodeList, "asda");
  const arr = nodeList
    .filter((x) => x.shape != "edge")
    .filter((y) => y.productionId);
  console.log(arr, "bbb");
  const newArr = arr.map((x) => x.productionId);
  if (new Set(newArr).size != newArr.length) {
    ElMessage({
      message: "工序不可重复",
      type: "info",
    });
    return false;
  }

  return {
    nodeObject: submitFormData.nodeObject,
  };
};

//选取一个随机不重复的正整数id
const randomId = () => {
  const id = Math.floor(Math.random() * 100000000000000000);
  if (flowDefinitionNodeObj.value[id]) {
    randomId();
  } else {
    return id;
  }
};

const addVersion = () => {
  const idObg = {};
  for (let i = 0; i < submitFormData.flowDefinitionNodeList.length; i++) {
    const element = submitFormData.flowDefinitionNodeList[i];
    if (element.parentId == null && element.nodeName == "结束") {
      ElMessage({
        message: "有结束节点未连线，请配置",
        type: "warning",
      });
      return;
    }
    if (isNaN(element.id)) {
      if (idObg[element.id]) {
        element.id = idObg[element.id];
      } else {
        const id = randomId();
        idObg[element.id] = id;
        element.id = id;
      }
    }
    if (isNaN(element.parentId) && element.nodeName != "开始") {
      if (idObg[element.parentId]) {
        element.parentId = idObg[element.parentId];
      } else {
        const id = randomId();
        idObg[element.parentId] = id;
        element.parentId = id;
      }
    }
    //nodeButtonSet转成字符串类型，用逗号隔开
    if (element.nodeButtonSet) {
      element.nodeButtonSet = element.nodeButtonSet.join(",");
    }
  }

  proxy.post("/flowDefinition/addVersion", submitFormData).then((res) => {
    ElMessage({
      message: "保存成功",
      type: "success",
    });
    useTagsViewStore().delView(router.currentRoute.value);
    history.go(-1);
  });
};

const pushRoom = (port: any) => {
  // if (port.node.shape == "end-btn") {
  //   flowDefinitionNodeObj.value[port.node.id] = {
  //     nodeName: "结束",
  //     nodeType: 99,
  //     id: port.id,
  //     nodeButtonSet: "",
  //     parentId: null,
  //   };
  // }
  if (port.node.shape == "handle-btn") {
    let nodeName = "";
    if (
      port.node.store &&
      port.node.store.data &&
      port.node.store.data.data &&
      port.node.store.data.data.title
    ) {
      nodeName = port.node.store.data.data.title;
    }
    flowNodeObj.value[port.node.id] = {
      nodeName: nodeName,
      id: port.node.id,
    };
  }
};

//用于存储流程定义节点数据
const antvInit = async (data) => {
  graph = new Graph({
    height: 600,
    container: document.getElementById("graph-container")!,
    grid: true,
    panning: {
      enabled: true,
      eventTypes: "rightMouseDown",
    },
    onPortRendered: pushRoom,
    mousewheel: {
      enabled: true,
      zoomAtMousePosition: true,
      modifiers: "ctrl",
      minScale: 0.5,
      maxScale: 3,
    },

    connecting: {
      allowLoop: false,
      // router: 'manhattan',
      connector: {
        name: "rounded",
        args: {
          radius: 8,
        },
      },
      anchor: "center",
      connectionPoint: "anchor",
      allowBlank: false,
      snap: {
        radius: 20,
      },
      createEdge() {
        return new Shape.Edge({
          attrs: {
            line: {
              stroke: "#A2B1C3",
              strokeWidth: 2,
              targetMarker: {
                name: "block",
                width: 12,
                height: 8,
              },
            },
          },
          zIndex: 0,
        });
      },
      validateConnection({ targetMagnet }) {
        return !!targetMagnet;
      },
    },
    highlighting: {
      magnetAdsorbed: {
        name: "stroke",
        args: {
          attrs: {
            fill: "#5F95FF",
            stroke: "#5F95FF",
          },
        },
      },
    },
  });
  // nextTick(() => {
  //   graph.use(
  //     new MiniMap({
  //       container: document.getElementById("minimap"),
  //       width: 200,
  //       height: 160,
  //       scalable: false,
  //     })
  //   );
  // });

  const stencil = new Stencil({
    title: "流程图",
    target: graph,
    stencilGraphWidth: 360,
    stencilGraphHeight: 280,
    collapsable: true,
    groups: [
      {
        title: "基础流程图",
        name: "group1",
      },
    ],
    layoutOptions: {
      columns: 1,
      columnWidth: 170,
      rowHeight: 100,
    },
  });
  document.getElementById("stencil")!.appendChild(stencil.container);
  // #region 使用插件
  graph
    .use(
      new Transform({
        resizing: true,
        rotating: true,
      })
    )
    .use(
      new Selection({
        enabled: true,
        rubberband: true,
        showNodeSelectionBox: true,
      })
    )
    .use(
      new Snapline({
        enabled: true,
      })
    )
    .use(
      new Keyboard({
        enabled: true,
      })
    )
    .use(
      new Clipboard({
        enabled: true,
      })
    )
    .use(
      new History({
        enabled: true,
      })
    );

  // 控制连接桩显示/隐藏
  const showPorts = (ports: NodeListOf<SVGElement>, show: boolean) => {
    for (let i = 0, len = ports.length; i < len; i += 1) {
      ports[i].style.visibility = show ? "visible" : "hidden";
    }
  };

  // 监听添加节点
  graph.on("node:added", ({ node }) => {});
  graph.on("node:mouseenter", () => {
    const container = document.getElementById("graph-container")!;
    const ports = container.querySelectorAll(
      ".x6-port-body"
    ) as NodeListOf<SVGElement>;
    showPorts(ports, true);
  });
  graph.on("node:mouseleave", () => {
    const container = document.getElementById("graph-container")!;
    const ports = container.querySelectorAll(
      ".x6-port-body"
    ) as NodeListOf<SVGElement>;
    showPorts(ports, false);
  });
  // #endregion
  graph.on("cell:click", ({ e, x, y, cell, view }) => {
    if (cell.shape === "start-btn") {
      return;
    }
    if (cell.shape === "end-btn") {
      return;
    }
    if (cell.shape === "handle-btn" || cell.shape === "edge") {
      // ElMessageBox.confirm("是否删除", "提示", {
      //   confirmButtonText: "确定",
      //   cancelButtonText: "取消",
      //   type: "warning",
      // }).then(() => {
      //   graph.removeNode(cell.id);
      // });
      // return;
      formData.data.id = cell.id;
      formData.data.cell = cell;
      console.log(cell, "sss");

      if (cell.store.data.data) {
        formData.data.nodeName = cell.store.data.data.title;
      } else if (cell.store.data) {
        formData.data.nodeName = cell.store.data.label;
      } else {
        formData.data.nodeName = "";
      }
      dialogVisible.value = true;
    }
  });
  // #region 初始化图形
  const ports = {
    groups: {
      top: {
        position: "top",
        attrs: {
          circle: {
            r: 4,
            magnet: true,
            stroke: "#5F95FF",
            strokeWidth: 1,
            fill: "#fff",
            style: {
              visibility: "hidden",
            },
          },
        },
      },
      right: {
        position: "right",
        attrs: {
          circle: {
            r: 4,
            magnet: true,
            stroke: "#5F95FF",
            strokeWidth: 1,
            fill: "#fff",
            style: {
              visibility: "hidden",
            },
          },
        },
      },
      bottom: {
        position: "bottom",
        attrs: {
          circle: {
            r: 4,
            magnet: true,
            stroke: "#5F95FF",
            strokeWidth: 1,
            fill: "#fff",
            style: {
              visibility: "hidden",
            },
          },
        },
      },
      left: {
        position: "left",
        attrs: {
          circle: {
            r: 4,
            magnet: true,
            stroke: "#5F95FF",
            strokeWidth: 1,
            fill: "#fff",
            style: {
              visibility: "hidden",
            },
          },
        },
      },
    },
    items: [
      {
        group: "top",
      },
      {
        group: "right",
      },
      {
        group: "bottom",
      },
      {
        group: "left",
      },
    ],
  };
  Graph.registerNode(
    "custom-rect",
    {
      inherit: "rect",
      width: 66,
      height: 36,
      attrs: {
        body: {
          strokeWidth: 1,
          stroke: "#5F95FF",
          fill: "#EFF4FF",
        },
        text: {
          fontSize: 12,
          fill: "#262626",
        },
      },
      ports: { ...ports },
    },
    true
  );

  register({
    shape: "start-btn",
    width: 150,
    height: 90,
    component: startBtn,
    effect: ["title"],
    ports: { ...ports },
    data: {
      title: 80,
    },
  });
  register({
    shape: "handle-btn",
    width: 150,
    height: 90,
    effect: ["title"],
    component: handleBtn,
    ports: { ...ports },
  });
  register({
    shape: "branch-btn",
    width: 150,
    height: 90,
    effect: ["title"],
    component: branchBtn,
    ports: { ...ports },
  });

  register({
    shape: "end-btn",
    width: 150,
    height: 90,
    effect: ["title"],
    component: endBtn,
    ports: { ...ports },
  });
  // const r1 = graph.createNode({
  // 	shape: 'start-btn',
  // 	label: '开始',
  // 	zIndex: 100,
  // 	attrs: {
  // 		body: {
  // 			rx: 20,
  // 			ry: 26,
  // 		},
  // 	},
  // 	data: {
  // 		title: 80,
  // 	},

  // })
  const r2 = graph.createNode({
    shape: "handle-btn",
    label: "办理",
    zIndex: 100,
    attrs: {
      body: {
        rx: 40,
        ry: 46,
      },
    },
  });

  const r3 = graph.createNode({
    shape: "branch-btn",
    label: "分支",
    zIndex: 100,
    attrs: {
      body: {
        rx: 40,
        ry: 46,
      },
    },
  });

  const r4 = graph.createNode({
    shape: "end-btn",
    label: "结束",
    zIndex: 100,
    attrs: {
      body: {
        rx: 20,
        ry: 26,
      },
    },
  });

  let arr = [];
  const resList = await proxy.post("/productionProcesses/page", {
    pageNum: 1,
    pageSize: 9999,
  });
  arr = resList.rows.map((x) => {
    return graph.createNode({
      shape: "handle-btn",
      label: x.name,
      productionId: x.id,
      zIndex: 100,
      attrs: {
        body: {
          rx: 20,
          ry: 26,
        },
      },
    });
  });

  stencil.load([...arr], "group1");

  if (data) {
    graph.fromJSON(data);
  } else {
    graph.addNode({
      shape: "start-btn",
      x: 300,
      y: 20,
      label: "开始",
      id: 1,
      attrs: {},
    });

    graph.addNode({
      shape: "end-btn",
      x: 300,
      y: 300,
      label: "结束",
      id: 99,
      attrs: {},
    });
  }
};

const getFlowInfo = (data) => {
  if (data) {
    antvInit(data);
  } else {
    antvInit();
  }
};

onActivated(() => {});
onDeactivated(() => {
  console.log(window.document.getElementById("minimap").children);
  if (window.document.getElementById("minimap").children.length > 1) {
    window.document.getElementById("minimap").children[0].remove();
  }
});
onMounted(() => {
  if (proxy.nodeObject) {
    let data = JSON.parse(proxy.nodeObject);
    getFlowInfo(data);
  } else {
    getFlowInfo();
  }
  setTimeout(() => {
    if (window.document.getElementById("minimap").children.length > 1) {
      window.document.getElementById("minimap").children[0].remove();
    }
  }, 500);
});
defineExpose({
  submitAll,
});
</script>
<style lang="scss" scope>
#minimap .x6-widget-minimap {
  border: 1px solid #dcdcdc;
}
.x6-widget-stencil-group-title {
  display: none !important;
}
.x6-widget-stencil-title {
  display: none;
}
.x6-widget-stencil-content {
  top: 0 !important;
  &::-webkit-scrollbar {
    width: 2px !important;
    height: 2px !important;
  }
}
.vueFlow1 {
  // position: relative;
  display: flex;
  justify-content: space-between;
  overflow: hidden;
  height: 600px;
  .x6-graph {
    width: 100% !important;
  }
  #stencil {
    // position: fixed;
    position: absolute;
    top: 50px;
    left: 30px;
    z-index: 100;
    width: 190px;
    height: 600px;
    background: #fff;
    overflow: hidden;
    // background: #fff;
    border-radius: 10px;
    // border: 1px solid #eee;
  }
  #container {
  }
  #graph-container {
    width: 100%;
    // width: 100%;
    // position: absolute;
    // right: 0;
    // top: 0;
  }
}

#stencil .x6-widget-stencil-content .x6-widget-stencil-group-content .x6-graph {
  height: 900px !important;
}
</style>
