import { buildEdgeRoute, getEdgeChannelOffset, getItemPixelRect } from "../utils/edgeRouting.js";
import { useMemo } from "react";
//#region src/components/pisellFloorMapLayout/hooks/useFloorMapEdgeViewModel.ts
/**
* 根据 edges + 图元矩形计算连线路由
*/
function extractRouteSegments(points) {
	const segs = [];
	for (let i = 0; i < points.length - 1; i++) {
		const [x1, y1] = points[i];
		const [x2, y2] = points[i + 1];
		if (y1 === y2 && x1 !== x2) segs.push({
			orientation: "h",
			key: y1,
			a: Math.min(x1, x2),
			b: Math.max(x1, x2)
		});
		else if (x1 === x2 && y1 !== y2) segs.push({
			orientation: "v",
			key: x1,
			a: Math.min(y1, y2),
			b: Math.max(y1, y2)
		});
	}
	return segs;
}
function segmentsOverlap(a, b) {
	if (a.orientation !== b.orientation) return false;
	if (a.key !== b.key) return false;
	return Math.max(a.a, b.a) < Math.min(a.b, b.b);
}
function routesShareChannel(a, b) {
	const segsA = extractRouteSegments(a);
	const segsB = extractRouteSegments(b);
	for (const sa of segsA) for (const sb of segsB) if (segmentsOverlap(sa, sb)) return true;
	return false;
}
/** 同一目标的多条边在末段竖线处必然共线，需主动分配通道错位 */
function edgesShareTarget(a, b) {
	return a.targetId === b.targetId || a.sourceId === b.sourceId;
}
function useFloorMapEdgeViewModel(params) {
	const { edges = [], items, cellSize, itemUnit, itemGap, pendingRectsById, pendingRoutingByEdge } = params;
	return useMemo(() => {
		const rectsById = /* @__PURE__ */ new Map();
		for (const item of items) rectsById.set(item.id, getItemPixelRect(item, {
			cellSize,
			itemUnit,
			itemGap,
			override: pendingRectsById === null || pendingRectsById === void 0 ? void 0 : pendingRectsById[item.id]
		}));
		/** Pass 1：所有 edge 用默认通道（offset = 0）计算一次 */
		const naive = edges.map((edge) => ({
			edge,
			route: buildEdgeRoute(edge, rectsById, { routingOverride: pendingRoutingByEdge === null || pendingRoutingByEdge === void 0 ? void 0 : pendingRoutingByEdge[edge.id] })
		}));
		/**
		* Pass 2：对共享通道的 edges 分配错位 offset。
		* 用 union-find 风格：按 edges 出现顺序遍历，与已选 routes 比对，若冲突则用下一个 offset。
		*/
		const routes = [];
		const accepted = [];
		const acceptedEdges = [];
		for (let i = 0; i < naive.length; i++) {
			const { edge, route } = naive[i];
			if (!route) continue;
			let chosen = route;
			let attempt = 0;
			const maxAttempts = 10;
			while (attempt < maxAttempts) {
				if (!accepted.some((r, idx) => {
					const other = acceptedEdges[idx];
					return routesShareChannel(chosen.points, r.points) || other != null && edgesShareTarget(edge, other);
				})) break;
				attempt += 1;
				const re = buildEdgeRoute(edge, rectsById, {
					channelOffset: getEdgeChannelOffset(attempt),
					routingOverride: pendingRoutingByEdge === null || pendingRoutingByEdge === void 0 ? void 0 : pendingRoutingByEdge[edge.id]
				});
				if (!re) break;
				chosen = re;
			}
			accepted.push(chosen);
			acceptedEdges.push(edge);
			routes.push(chosen);
		}
		return {
			routes,
			rectsById
		};
	}, [
		edges,
		items,
		cellSize,
		itemUnit,
		itemGap,
		pendingRectsById,
		pendingRoutingByEdge
	]);
}
//#endregion
export { useFloorMapEdgeViewModel };
