<template>
	<el-container class="flow-editor">
		<left-panel v-if="lf" :lf="lf"></left-panel>
		<div ref="containerRef" class="flow-container"></div>
		<right-panel v-if="lf" :lf="lf" :node="activeNode"></right-panel>
		<menu-panel v-if="lf" :lf="lf" class="menu-panel"/>
	</el-container>
</template>

<script setup>
import {ref, onMounted, onUnmounted} from "vue"
import LogicFlow from "@logicflow/core"
import {MiniMap, Snapshot, ProximityConnect} from "@logicflow/extension"
import {Dagre} from "@logicflow/layout";
import "@logicflow/core/lib/style/index.css"
import "@logicflow/extension/lib/style/index.css"
import leftPanel from "./left.vue"
import menuPanel from "./menu.vue"
import rightPanel from "./right.vue"
import {StartNodeModel, StartNodeView, START_NODE_TYPES} from "./model/StartNode"
import {EventNodeModel, EventNodeView, EVENT_NODE_TYPES} from "./model/EventNode"
import {GatewayNodeModel, GatewayNodeView, GATEWAY_NODE_TYPES} from "./model/GatewayNode"
import {CatchNodeModel, CatchNodeView, CATCH_NODE_TYPES} from "./model/CatchNode"
import {EndNodeModel, EndNodeView, END_NODE_TYPES} from "./model/EndNode"
import {CustomLineModel, CustomLine, CUSTOM_LINE} from "./model/CustomLine"
import {ElMessageBox} from 'element-plus'
import {useI18n} from "vue-i18n"

defineOptions({
	name: 'toolsFlow'
})

const containerRef = ref(HTMLElement | null);
const {t} = useI18n()
let lf = ref(LogicFlow | null);
let activeNode = ref({})

onMounted(() => {
	init()
	window.addEventListener("keydown", handleKeydown);
})

onUnmounted(() => {
	window.removeEventListener("keydown", handleKeydown);
})

function init() {
	lf.value = new LogicFlow({
		container: containerRef.value,
		grid: {
			size: 20,              // 网格间距
			visible: true,         // 显示网格
			type: "dot",           // dot(点) / mesh(格子线)
			config: {
				color: "#dcdfe6",    // 网格颜色
				thickness: 1,        // 网格粗细
			}
		},
		background: {
			color: "#f7f8fa"
		},
		plugins: [MiniMap, Snapshot, ProximityConnect, Dagre],
		pluginsOptions: {
			miniMap: {
				headerTitle: '小地图',
				isShowHeader: true,
				showEdge: true,
				isShowCloseIcon: true,
				bottomPosition: 10,
				rightPosition: 10
			},
			proximityConnect: {
				enable: true,
				type: 'anchor'
			}
		}
	})

	/** 注册自定义节点 */
	registerCustomNodes()
	/** 注册自定义连线 */
	registerCustomEdge()

	/** 监听节点点击 */
	lf.value.on("node:click", ({data}) => {
		activeNode.value = data
	})

	lf.value.on("edge:click", ({data}) => {
		activeNode.value = data
	})

	lf.value.on("blank:click", () => {
		activeNode.value = {}
	});

	// 初始渲染
	lf.value.render({
		nodes: [
			{id: "1", type: "start-basic", x: 200, y: 200, text: "开始节点"},
			{id: "2", type: "event-approval", x: 400, y: 200, text: "审批节点"},
		],
		edges: [
			{sourceNodeId: "1", targetNodeId: "2", type: CUSTOM_LINE.LINE_TYPE}
		]
	})
}

/** 注册自定义节点 */
function registerCustomNodes() {
	if (!lf.value) return;

	// 开始节点
	Object.values(START_NODE_TYPES).map(i => {
		lf.value.register({
			type: i,
			view: StartNodeView,
			model: StartNodeModel
		});
	})

	// 事件节点
	Object.values(EVENT_NODE_TYPES).map(i => {
		lf.value.register({
			type: i,
			view: EventNodeView,
			model: EventNodeModel
		});
	})

	// 网关节点
	Object.values(GATEWAY_NODE_TYPES).map(i => {
		lf.value.register({
			type: i,
			view: GatewayNodeView,
			model: GatewayNodeModel
		});
	})

	// 捕获节点
	Object.values(CATCH_NODE_TYPES).map(i => {
		lf.value.register({
			type: i,
			view: CatchNodeView,
			model: CatchNodeModel
		});
	})

	// 结束节点
	Object.values(END_NODE_TYPES).map(i => {
		lf.value.register({
			type: i,
			view: EndNodeView,
			model: EndNodeModel
		});
	})
}

function registerCustomEdge() {
	if (!lf.value) return;

	lf.value.register({
		type: CUSTOM_LINE.LINE_TYPE,
		view: CustomLine,
		model: CustomLineModel
	});
	lf.value.setDefaultEdgeType(CUSTOM_LINE.LINE_TYPE);
}

/** 更新节点文本 */
function updateNodeText() {
	if (!lf.value || !activeNode.value) return;
	lf.value.updateText(activeNode.value.id, activeNode.value.text.value);
}

/** 更新节点属性 */
function updateNodeProps() {
	if (!lf.value || !activeNode.value) return;
	lf.value.setProperties(activeNode.value.id, activeNode.value.properties);
}

// 快捷键设置
const handleKeydown = (event) => {
	// if (event.key === "Delete" || event.key === "Backspace") {
	// 	if (Object.keys(activeNode.value).length !== 0) {
	// 		ElMessageBox.confirm(
	// 			activeNode.value.type === 'line' ? t('flow.deleteLine') : t('flow.deleteNode'),
	// 			t('system.warning'),
	// 			{
	// 				confirmButtonText: t('system.ok'),
	// 				cancelButtonText: t('system.cancel'),
	// 				type: 'warning',
	// 			}
	// 		).then(() => {
	// 			if (activeNode.value.type === 'line') {
	// 				lf.value.deleteEdge(activeNode.value.id);
	// 			} else {
	// 				lf.value.deleteNode(activeNode.value.id);
	// 			}
	// 		}).catch(() => {
	// 		})
	// 	}
	// 	return
	// }

	const directionKeys = ['ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight'];
	if (directionKeys.includes(event.key)) {
		// 获取当前选中的所有元素
		const selectedElements = lf.value.getSelectElements();
		const selectedNodes = selectedElements.nodes;

		// 如果没有节点被选中，则不执行操作
		if (selectedNodes.length === 0) return;

		// 根据按键计算移动偏移量
		let deltaX = 0;
		let deltaY = 0;
		switch (event.key) {
			case 'ArrowUp':
				deltaY = -1;
				break;
			case 'ArrowDown':
				deltaY = 1;
				break;
			case 'ArrowLeft':
				deltaX = -1;
				break;
			case 'ArrowRight':
				deltaX = 1;
				break;
		}

		// 遍历所有选中的节点进行移动
		selectedNodes.forEach(node => {
			const newNodeX = node.x + deltaX;
			const newNodeY = node.y + deltaY;

			// 获取节点模型并移动
			const nodeModel = lf.value.getNodeModelById(node.id);
			if (nodeModel) {
				nodeModel.moveTo({x: newNodeX, y: newNodeY});
			}
		});
		return
	}
}
</script>

<style lang="scss" scoped>
.flow-editor {
	display: flex;
	height: 100%;
	position: relative;

	.flow-container {
		flex: 1;
		width: 100%;
		height: calc(100% - 3px);
	}

	:deep(.lf-mini-map) {
		background: #FFF;
		border: 1px solid #eee;
		padding: 2px;
	}

	:deep(.lf-mini-map-header) {
		background: #f5f5f5;
		border: 0;
		height: 24px;
		line-height: 24px;
	}

	:deep(.lf-mini-map-close) {
		height: 22px;
		width: 22px;
	}

	:deep(.lf-minimap-viewport) {
		border: 2px solid #409EFF;
		background-color: transparent;
	}
}

</style>
