import { getPortLabelPosition, resolveEdgeCenterLabelPositions } from "../utils/edgeRouting.js";
import React, { useMemo } from "react";
import classNames from "classnames";
import "./EdgeLayer.less";
//#region src/components/pisellFloorMapLayout/components/EdgeLayer.tsx
/**
* EdgeLayer - 拓扑连线 SVG 层（正交折线 + 端口标签）
*/
const PREFIX = "pisell-floor-map-layout";
/** 中段手柄基础视觉尺寸（px），实际渲染会按 viewportScale 反向缩放 */
const SEGMENT_HANDLE_BASE_SIZE = 12;
/** 段长 < 该值（px）时不渲染手柄，避免极短段误触 */
const SEGMENT_HANDLE_MIN_LENGTH = 16;
function resolveEdgeStroke(edge, appearance, selected) {
	var _edge$status, _edge$strokeWidth3;
	if (selected) {
		var _edge$strokeWidth;
		return {
			stroke: appearance.edgeSelectedStroke,
			strokeWidth: ((_edge$strokeWidth = edge.strokeWidth) !== null && _edge$strokeWidth !== void 0 ? _edge$strokeWidth : 1.5) + 1
		};
	}
	if (edge.color) {
		var _edge$strokeWidth2;
		return {
			stroke: edge.color,
			strokeWidth: (_edge$strokeWidth2 = edge.strokeWidth) !== null && _edge$strokeWidth2 !== void 0 ? _edge$strokeWidth2 : 1.5,
			strokeDasharray: edge.dashed ? "6 4" : void 0
		};
	}
	const status = (_edge$status = edge.status) !== null && _edge$status !== void 0 ? _edge$status : "unknown";
	const style = appearance.edgeStatusStyles[status];
	return {
		stroke: style.stroke,
		strokeWidth: (_edge$strokeWidth3 = edge.strokeWidth) !== null && _edge$strokeWidth3 !== void 0 ? _edge$strokeWidth3 : 1.5,
		strokeDasharray: edge.dashed || style.dashed ? "6 4" : void 0
	};
}
function PortLabel(props) {
	const { x, y, text, appearance } = props;
	const estW = Math.max(32, text.length * 6.5 + 12);
	const h = 18;
	return /* @__PURE__ */ React.createElement("g", { className: `${PREFIX}-edge-port-label` }, /* @__PURE__ */ React.createElement("rect", {
		x: x - estW / 2,
		y: y - h / 2,
		width: estW,
		height: h,
		rx: 4,
		fill: appearance.edgePortLabelBackground,
		stroke: appearance.edgePortLabelBorder,
		strokeWidth: 1
	}), /* @__PURE__ */ React.createElement("text", {
		x,
		y: y + 4,
		textAnchor: "middle",
		fontSize: 11,
		fill: appearance.edgePortLabelText
	}, text));
}
function EdgeLayer(props) {
	const { width, height, contentOffsetX = 0, contentOffsetY = 0, edges, routes, rectsById, appearance, mode, selectedEdgeId, ghostPathD, onEdgeClick, viewportScale = 1, onSegmentDragStart, className } = props;
	const safeScale = Math.max(viewportScale, .01);
	const handleSize = SEGMENT_HANDLE_BASE_SIZE / safeScale;
	const handleHalf = handleSize / 2;
	const edgeById = useMemo(() => {
		const m = /* @__PURE__ */ new Map();
		for (const e of edges) m.set(e.id, e);
		return m;
	}, [edges]);
	const routeById = useMemo(() => {
		const m = /* @__PURE__ */ new Map();
		for (const r of routes) m.set(r.edgeId, r);
		return m;
	}, [routes]);
	/** 同目标多边时错开 connection_type 标签，避免叠在一起 */
	const centerLabelByEdgeId = useMemo(() => resolveEdgeCenterLabelPositions(routes.map((route) => {
		const edge = edgeById.get(route.edgeId);
		if (!edge) return null;
		return {
			edgeId: route.edgeId,
			sourceId: edge.sourceId,
			targetId: edge.targetId,
			points: route.points,
			label: edge.label
		};
	}).filter((row) => row != null), {
		placement: "target-tail",
		rectsById
	}), [
		routes,
		edgeById,
		rectsById
	]);
	return /* @__PURE__ */ React.createElement("svg", {
		className: classNames(`${PREFIX}-edge-layer`, className),
		width,
		height,
		style: {
			position: "absolute",
			left: contentOffsetX,
			top: contentOffsetY,
			pointerEvents: "none",
			overflow: "visible"
		},
		"aria-hidden": mode === "read"
	}, /* @__PURE__ */ React.createElement("g", { className: `${PREFIX}-edge-layer-inner` }, routes.map((route) => {
		const edge = edgeById.get(route.edgeId);
		if (!edge) return null;
		const selected = selectedEdgeId === edge.id;
		const stroke = resolveEdgeStroke(edge, appearance, selected);
		return /* @__PURE__ */ React.createElement("g", {
			key: edge.id,
			className: `${PREFIX}-edge-group`
		}, /* @__PURE__ */ React.createElement("path", {
			d: route.pathD,
			fill: "none",
			stroke: stroke.stroke,
			strokeWidth: stroke.strokeWidth,
			strokeDasharray: stroke.strokeDasharray,
			strokeLinecap: "round",
			strokeLinejoin: "round",
			className: classNames(`${PREFIX}-edge-path`, {
				[`${PREFIX}-edge-path--selected`]: selected,
				[`${PREFIX}-edge-path--interactive`]: mode === "edit"
			}),
			style: {
				pointerEvents: mode === "edit" ? "stroke" : "none",
				cursor: mode === "edit" ? "pointer" : void 0
			},
			onClick: mode === "edit" && onEdgeClick ? (ev) => {
				ev.stopPropagation();
				onEdgeClick(edge.id, ev);
			} : void 0
		}), edge.label && route.points.length >= 2 ? (() => {
			const labelPos = centerLabelByEdgeId.get(edge.id);
			if (!labelPos) return null;
			return /* @__PURE__ */ React.createElement(PortLabel, {
				x: labelPos.x,
				y: labelPos.y,
				text: edge.label,
				appearance
			});
		})() : null);
	}), edges.map((edge) => {
		var _edge$sourceAnchor, _edge$targetAnchor;
		const route = routeById.get(edge.id);
		const srcRect = rectsById.get(edge.sourceId);
		const tgtRect = rectsById.get(edge.targetId);
		if (!route || !srcRect || !tgtRect) return null;
		const sourceAnchor = (_edge$sourceAnchor = edge.sourceAnchor) !== null && _edge$sourceAnchor !== void 0 ? _edge$sourceAnchor : "right";
		const targetAnchor = (_edge$targetAnchor = edge.targetAnchor) !== null && _edge$targetAnchor !== void 0 ? _edge$targetAnchor : "left";
		const spLabel = getPortLabelPosition(srcRect, sourceAnchor);
		const tpLabel = getPortLabelPosition(tgtRect, targetAnchor);
		return /* @__PURE__ */ React.createElement("g", { key: `${edge.id}-labels` }, edge.sourceLabel ? /* @__PURE__ */ React.createElement(PortLabel, {
			x: spLabel.x,
			y: spLabel.y,
			text: edge.sourceLabel,
			appearance
		}) : null, edge.targetLabel ? /* @__PURE__ */ React.createElement(PortLabel, {
			x: tpLabel.x,
			y: tpLabel.y,
			text: edge.targetLabel,
			appearance
		}) : null);
	}), mode === "edit" && selectedEdgeId && onSegmentDragStart ? (() => {
		const route = routeById.get(selectedEdgeId);
		if (!route) return null;
		const pts = route.points;
		if (pts.length < 2) return null;
		const lastSegIdx = pts.length - 2;
		const handles = [];
		for (let i = 0; i <= lastSegIdx; i++) {
			const role = i === 0 ? "first" : i === lastSegIdx ? "last" : "inner";
			const [x1, y1] = pts[i];
			const [x2, y2] = pts[i + 1];
			let axis;
			let position;
			let length;
			let midX;
			let midY;
			if (y1 === y2 && x1 !== x2) {
				axis = "h";
				position = y1;
				length = Math.abs(x2 - x1);
				midX = (x1 + x2) / 2;
				midY = y1;
			} else if (x1 === x2 && y1 !== y2) {
				axis = "v";
				position = x1;
				length = Math.abs(y2 - y1);
				midX = x1;
				midY = (y1 + y2) / 2;
			} else continue;
			if (length < SEGMENT_HANDLE_MIN_LENGTH) continue;
			handles.push({
				key: `${role}-${i}`,
				role,
				segmentIndex: i,
				axis,
				position,
				length,
				midX,
				midY
			});
		}
		if (handles.length === 0) return null;
		return /* @__PURE__ */ React.createElement("g", {
			className: `${PREFIX}-edge-segment-handles`,
			pointerEvents: "auto"
		}, handles.map((h) => /* @__PURE__ */ React.createElement("rect", {
			key: h.key,
			x: h.midX - handleHalf,
			y: h.midY - handleHalf,
			width: handleSize,
			height: handleSize,
			rx: handleHalf,
			ry: handleHalf,
			className: classNames(`${PREFIX}-edge-segment-handle`, `${PREFIX}-edge-segment-handle--${h.axis}`, `${PREFIX}-edge-segment-handle--${h.role}`),
			fill: appearance.edgeSelectedStroke,
			stroke: "#fff",
			strokeWidth: 1.5 / safeScale,
			style: {
				cursor: h.axis === "h" ? "ns-resize" : "ew-resize",
				touchAction: "none"
			},
			onPointerDown: (ev) => {
				ev.stopPropagation();
				ev.preventDefault();
				onSegmentDragStart({
					edgeId: selectedEdgeId,
					role: h.role,
					segmentIndex: h.segmentIndex,
					axis: h.axis,
					startPosition: h.position,
					clientX: ev.clientX,
					clientY: ev.clientY,
					segmentLength: h.length
				});
			}
		})));
	})() : null, ghostPathD ? /* @__PURE__ */ React.createElement("path", {
		d: ghostPathD,
		fill: "none",
		stroke: appearance.edgeGhostStroke,
		strokeWidth: 1.5,
		strokeDasharray: "4 4",
		strokeLinecap: "round",
		pointerEvents: "none"
	}) : null));
}
//#endregion
export { EdgeLayer };
