<template lang="">
	<div class="vueFlow">
		<div id="container"></div>
		<div id="stencil"></div>
		<div id="graph-container"></div>
		<div id="minimap"></div>
	</div>
	<el-button @click="submitAll" type="primary" style="margin-top:15px">保存</el-button>
	<el-dialog
		title="节点信息配置"
		v-model="dialogVisible"
		width="800"
		v-loading="loading"
	>
		<byForm
			:formConfig="formType === 'handle-btn' ? formConfig : branchBtnConfig"
			:formOption="formOption"
			v-model="formData.data"
			:rules="rules"
			ref="byform"
		>
		</byForm>
		<template #footer>
			<el-button @click="dialogVisible = false" size="default"
				>取 消</el-button
			>
			<el-button
				type="danger"
				@click="deleteFlowDefinitionNodeObj()"
				size="default"
				:loading="submitLoading"
			>
				删 除
			</el-button>
			<el-button
				type="primary"
				@click="submitForm('byform')"
				size="default"
				:loading="submitLoading"
			>
				确 定
			</el-button>
		</template>
	</el-dialog>
	<el-dialog
		title="节点信息配置"
		v-model="startModalType"
		width="500"
		v-loading="loading"
	>
		<div>
			节点后执行方法
			<el-input style="margin-top:10px" v-model="handlingMethod"></el-input>
		</div>
		<template #footer>
  <el-button @click="startModalType = false" size="default">取 消</el-button>
  <el-button type="primary" @click="startModalType = false" size="default" :loading="submitLoading">
    确 定
  </el-button>
</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";

defineProps({
  title: {
    type: Object,
    default: "",
  },
});
const { proxy } = getCurrentInstance();
const internalInstance = getCurrentInstance();
const dialogVisible = ref(false);
const modalType = ref("add");
const loading = ref(false);
const submitLoading = ref(false);
let formType = ref(1); //1办理 2分支
const formData = reactive({
  data: {
    userName: "",
    password: "",
  },
});
const startModalType = ref(false);
const handlingMethod = ref("");
const byform = ref(null);
const flowDefinitionNodeObj = ref({});
const rules = reactive({
  nodeName: [
    {
      required: true,
      message: "请输入节点名称",
      trigger: "blur",
    },
  ],
  handleObjectType: [
    {
      required: true,
      message: "办理人类型不能为空",
      trigger: "blur",
    },
  ],
  handleObjectId: [
    {
      required: true,
      message: "办理人不能为空",
      trigger: "blur",
    },
  ],
});
const branchBtnConfig = computed(() => {
  return [
    {
      type: "input",
      prop: "nodeName",
      label: "节点名称",
      required: true,
      itemType: "text",
    },
  ];
});
const formConfig = computed(() => {
  return [
    {
      type: "input",
      prop: "nodeName",
      label: "节点名称",
      required: true,
      itemType: "text",
    },
    {
      type: "select",
      prop: "handleObjectType",
      label: "办理人",
      placeholder: "请选择办理人类型",
      required: true,
      itemWidth: 50,
      fn: (e) => {
        gethandleObjectList(e, true);
      },
      //1用户 2部门负责人 3部门总监 4岗位 5角色
      data: [
        {
          label: "用户",
          value: 1,
        },
        {
          label: "部门负责人",
          value: 2,
        },
        {
          label: "部门总监",
          value: 3,
        },
        {
          label: "岗位",
          value: 4,
        },
        {
          label: "角色",
          value: 5,
        },
      ],
    },
    // {
    // 	type: "treeSelect",
    // 	prop: "handleObjectId",
    // 	label: "请选择办理人",
    // 	itemWidth: 30,
    // 	data: [],
    // },
    {
      type: "select",
      label: "",
      itemWidth: 50,
      prop: "handleObjectId",
      placeholder: "请选择办理人",
      data: [],
    },
    {
      type: "input",
      prop: "handlingMethod",
      label: "节点后置执行方法",
      required: true,
      itemType: "text",
    },
    {
      type: "input",
      prop: "jumpCondition",
      label: "条件表达式",
      required: true,
      itemType: "text",
    },
    {
      type: "checkbox",
      prop: "nodeButtonSet",
      label: "节点按钮",
      //1通过 2驳回 3返回上一步 4退回到发起人
      data: [
        {
          label: "通过",
          value: 1,
          disabled: true,
        },
        {
          label: "驳回",
          value: 2,
        },
        {
          label: "返回上一步",
          value: 3,
        },
        {
          label: "退回到发起人",
          value: 4,
        },
      ],
    },
    {
      type: "radio",
      prop: "jobNumber11",
      label: "审批意见必填",
      data: [
        {
          label: "是",
          value: 1,
        },
        {
          label: "否",
          value: 0,
        },
      ],
    },
  ];
});
const formOption = reactive({
  inline: true,
  labelWidth: 130,
  itemWidth: 100,
});
let graph;
const submitForm = () => {
  byform.value.handleSubmit((valid) => {
    flowDefinitionNodeObj.value[formData.data.id] = formData.data;
    dialogVisible.value = false;
    formData.data.cell.setData({
      title: formData.data.nodeName,
    });
  });
};

const submitFormData = {
  flowInfoId: null,
  titleTemplate: null,
  tenantId: Cookies.get("tenantId"),
  nodeObject: "",
  lineObject: "",
  flowDefinitionNodeList: [],
};
const submitAll = () => {
  if (proxy.title == "") {
    ElMessage({
      message: "请输入流程标题",
      type: "warning",
    });
    return;
  }
  submitFormData.titleTemplate = proxy.title;
  const nodeList = graph.toJSON().cells;
  submitFormData.nodeObject = JSON.stringify(nodeList);
  submitFormData.lineObject = JSON.stringify(flowDefinitionNodeObj.value);
  console.log(nodeList);
  const isStart = false;
  for (let i = 0; i < nodeList.length; i++) {
    const element = nodeList[i];
    //是办理节点
    if (
      element.shape != "start-btn" &&
      element.shape != "edge" &&
      element.shape != "end-btn"
    ) {
      if (!flowDefinitionNodeObj.value[element.id]) {
        ElMessage({
          message: "有节点未配置,请检查节点",
          type: "warning",
        });
        return;
      }
      submitFormData.flowDefinitionNodeList.push({
        ...flowDefinitionNodeObj.value[element.id],
        nodeType: element.shape == "branch-btn" ? 3 : 2,
      });
    }
    if (element.shape == "end-btn") {
      submitFormData.flowDefinitionNodeList.push({
        ...flowDefinitionNodeObj.value[element.id],
      });
    }
    if (element.shape == "start-btn") {
      submitFormData.flowDefinitionNodeList.push({
        nodeName: "开始",
        nodeType: 1,
        id: 1,
        parentId: 0,
        nodeButtonSet: [1],
        handlingMethod: handlingMethod.value,
      });
    }
    //说明是线
    if (element.shape == "edge") {
      if (!flowDefinitionNodeObj.value[element.target.cell]) {
        ElMessage({
          message: "有节点未配置,请检查节点",
          type: "warning",
        });
        return;
      }
      flowDefinitionNodeObj.value[element.target.cell].id = element.target.cell;
      flowDefinitionNodeObj.value[element.target.cell].parentId =
        element.source.cell;
      submitFormData.flowDefinitionNodeList = [];
    }
  }
  addVersion();
};

//选取一个随机不重复的正整数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);
  });
};

//将组数里的id和parentId转换成整正整数类型
const changeId = (arr) => {
  for (let i = 0; i < arr.length; i++) {
    const element = arr[i];
    element.id = parseInt(element.id);
    element.parentId = parseInt(element.parentId);
  }
};

const deleteFlowDefinitionNodeObj = (id) => {
  graph.removeNode(formData.data.id);
  delete flowDefinitionNodeObj.value[id];
  dialogVisible.value = false;
};

const gethandleObjectList = (e, flag) => {
  if (flag) {
    formData.data.handleObjectId = "";
  }

  if (e === 1) {
    proxy
      .get(
        "/tenantUser/list?pageNum=1&pageSize=1000&tenantId=" +
          submitFormData.tenantId,
        {}
      )
      .then((res) => {
        formConfig.value[2].data = res.rows.map((item) => {
          return {
            label: item.nickName,
            value: item.userId,
          };
        });
      });
  }
  if (e === 3 || e === 2) {
    proxy
      .get(
        "/tenantDept/list?pageNum=1&pageSize=1000&tenantId=" +
          submitFormData.tenantId,
        {}
      )
      .then((res) => {
        formConfig.value[2].data = res.data.map((item) => {
          return {
            label: item.deptName,
            value: item.deptId,
          };
        });
      });
  }
  if (e === 4) {
  }
  if (e === 5) {
    proxy
      .get(
        "/tenantRole/list?pageNum=1&pageSize=1000&tenantId=" +
          submitFormData.tenantId,
        {}
      )
      .then((res) => {
        formConfig.value[2].data = res.rows.map((item) => {
          return {
            label: item.roleName,
            value: item.roleId,
          };
        });
      });
  }
};

const getTenantDept = () => {};
getTenantDept();

const recursive = (data) => {
  data.map((item) => {
    item.label = item.deptName;
    item.id = item.deptId;
    if (item.children) {
      recursive(item.children);
    } else {
      item.children = [];
    }
  });
};

const pushRoom = (port: any) => {
  if (port.node.shape == "end-btn") {
    flowDefinitionNodeObj.value[port.node.id] = {
      nodeName: "结束",
      nodeType: 99,
      id: port.id,
      nodeButtonSet: "",
      parentId: null,
    };
  }
};
//用于存储流程定义节点数据

const antvInit = (data) => {
  graph = new Graph({
    height: 600,
    container: document.getElementById("graph-container")!,
    grid: true,
    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",
          },
        },
      },
    },
  });
  graph.use(
    new MiniMap({
      container: document.getElementById("minimap"),
    })
  );
  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: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 }) => {
    console.log(flowDefinitionNodeObj.value);
    console.log(cell);
    if (cell.shape === "start-btn") {
      startModalType.value = true;
      return;
    }
    if (cell.shape === "end-btn" || cell.shape === "edge") {
      ElMessageBox.confirm("是否删除", "提示", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning",
      }).then(() => {
        graph.removeNode(cell.id);
        // delete flowDefinitionNodeObj.value[id]
      });
      return;
    }
    formType.value = cell.shape;
    if (flowDefinitionNodeObj.value[cell.id]) {
      // 默认去调对应的处理人接口
      gethandleObjectList(
        flowDefinitionNodeObj.value[cell.id].handleObjectType
      );
      setTimeout(() => {
        formData.data = flowDefinitionNodeObj.value[cell.id];
        formData.data.cell = cell;
      }, 300);
    } else {
      formData.data = {
        id: cell.id,
        cell: cell,
        nodeButtonSet: [1],
      };
    }

    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,
      },
    },
  });
  stencil.load([r2, r3, r4], "group1");
  // const startNode = graph.addNode({
  // 	shape: 'custom-rect',
  // 	label: '开始',
  // 	id: 1,
  // 	x: 500,
  // 	y: 100,
  // })
  if (data) {
    graph.fromJSON(data);
  } else {
    graph.addNode({
      shape: "start-btn",
      x: 500,
      y: 20,
      label: "开始",
      id: 1,
      attrs: {},
    });
  }
};
const getFlowInfo = () => {
  proxy
    .post("/flowDefinition/getDetails", { id: submitFormData.id })
    .then((res) => {
      if (res.lineObject) {
        flowDefinitionNodeObj.value = JSON.parse(res.lineObject);
        for (const key in flowDefinitionNodeObj.value) {
          if (flowDefinitionNodeObj.value[key].nodeButtonSet) {
            flowDefinitionNodeObj.value[key].nodeButtonSet =
              flowDefinitionNodeObj.value[key].nodeButtonSet.map((item) => {
                return item * 1;
              });
          }
        }
      }
      if (res.nodeObject) {
        antvInit(JSON.parse(res.nodeObject));
      } else {
        antvInit();
      }
      for (const key in flowDefinitionNodeObj.value) {
        //延迟等待dom渲染完成
        setTimeout(() => {
          if (
            flowDefinitionNodeObj.value[key].nodeName != "结束" &&
            flowDefinitionNodeObj.value[key].cell != "开始"
          ) {
            let htmlNode = document.querySelector(
              "g[data-cell-id='" + key + "']"
            );
            //获取htmlNode节点下的title,修改title的内容
            htmlNode.getElementsByClassName("title")[0].innerHTML =
              flowDefinitionNodeObj.value[key].nodeName;
          }
        }, 2000);
      }
      dialogVisible.value = false;
    });
};
const router = useRouter();
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(() => {
  //获取url router参数
  submitFormData.flowInfoId = router.currentRoute.value.query.flowInfoId;
  submitFormData.id = router.currentRoute.value.query.id;
  submitFormData.tenantId = router.currentRoute.value.query.tenantId;
  if (submitFormData.flowInfoId) {
    getFlowInfo();
    // antvInit()
    // setTimeout(() => {
    // 	for (let i = 0; i < dataJson.flowDefinitionNodeList.length; i++) {
    // 		const element = dataJson.flowDefinitionNodeList[i];
    // 		console.log(element)
    // 		if(!element.cell) {
    // 			continue
    // 		}
    // 		if( element.cell.nodeName != '开始' && element.cell.nodeName != '结束'){
    // 			flowDefinitionNodeObj.value[element.cell.id] = element
    // 			flowDefinitionNodeObj.value[element.cell.id].nodeButtonSet = element.nodeButtonSet.split(',')
    // 			graph.addNode({
    // 				shape: 'handle-btn',
    // 				x: element.cell.position.x,
    // 				y: element.cell.position.y,
    // 				label: '办理',
    // 				id:element.cell.id,
    // 				attrs: {

    // 				},
    // 			})
    // 		}

    // 	}
    // 	console.log(flowDefinitionNodeObj.value)
    // }, 1000);
  }
  setTimeout(() => {
    if (window.document.getElementById("minimap").children.length > 1) {
      window.document.getElementById("minimap").children[0].remove();
    }
  }, 500);
});
</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;
  }
}
.vueFlow {
  position: relative;
  display: flex;
  justify-content: space-between;
  overflow: hidden;
  height: 600px;
  .x6-graph {
    width: 100% !important;
  }
  #stencil {
    position: fixed;
    top: 250px;
    left: 30px;
    z-index: 100;
    width: 190px;
    height: 550px;
    background: #fff;
    overflow: hidden;
    background: #eee;
    border-radius: 20px;
  }
  #container {
  }
  #graph-container {
    width: 100%;
    position: absolute;
    right: 0;
    top: 0;
  }
}
#stencil .x6-widget-stencil-content .x6-widget-stencil-group-content .x6-graph {
  height: 900px !important;
}
</style>