var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
  for (var name in all)
    __defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
  if (from && typeof from === "object" || typeof from === "function") {
    for (let key of __getOwnPropNames(from))
      if (!__hasOwnProp.call(to, key) && key !== except)
        __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
  }
  return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);

// src/components/pisellFloorMapLayout/hooks/useFloorMapEdgeEditing.ts
var useFloorMapEdgeEditing_exports = {};
__export(useFloorMapEdgeEditing_exports, {
  useFloorMapEdgeEditing: () => useFloorMapEdgeEditing
});
module.exports = __toCommonJS(useFloorMapEdgeEditing_exports);
var import_react = require("react");
var import_edgeRouting = require("../utils/edgeRouting");
var import_useFloorMapEdgeViewModel = require("./useFloorMapEdgeViewModel");
function newEdgeId() {
  return `edge_${Date.now()}_${Math.random().toString(36).slice(2, 9)}`;
}
function useFloorMapEdgeEditing(params) {
  const {
    enabled,
    config,
    items,
    mergedItems,
    cellSize,
    itemUnit,
    itemGap,
    contentOffsetRef,
    selectedId,
    setSelectedId,
    commitDraft,
    mapContentRef,
    scale = 1
  } = params;
  const [selectedEdgeId, setSelectedEdgeId] = (0, import_react.useState)(null);
  const [drawing, setDrawing] = (0, import_react.useState)(null);
  const [ghostEnd, setGhostEnd] = (0, import_react.useState)(
    null
  );
  const [drawingTarget, setDrawingTarget] = (0, import_react.useState)(null);
  const [pendingRectsById, setPendingRectsById] = (0, import_react.useState)({});
  const [pendingRoutingByEdge, setPendingRoutingByEdge] = (0, import_react.useState)({});
  const edges = (config == null ? void 0 : config.edges) ?? [];
  const { routes, rectsById } = (0, import_useFloorMapEdgeViewModel.useFloorMapEdgeViewModel)({
    edges,
    items,
    cellSize,
    itemUnit,
    itemGap,
    pendingRectsById,
    pendingRoutingByEdge
  });
  const clearEdgeSelection = (0, import_react.useCallback)(() => {
    setSelectedEdgeId(null);
  }, []);
  const selectEdge = (0, import_react.useCallback)(
    (edgeId) => {
      if (drawing) return;
      setSelectedEdgeId(edgeId);
      if (edgeId) setSelectedId(null);
    },
    [drawing, setSelectedId]
  );
  const selectNode = (0, import_react.useCallback)(
    (id) => {
      if (drawing) return;
      setSelectedId(id);
      if (id) setSelectedEdgeId(null);
    },
    [drawing, setSelectedId]
  );
  const clientToContent = (0, import_react.useCallback)(
    (clientX, clientY) => {
      const el = mapContentRef.current;
      if (!el) return null;
      const rect = el.getBoundingClientRect();
      const off = contentOffsetRef.current;
      return {
        x: (clientX - rect.left) / scale - off.x,
        y: (clientY - rect.top) / scale - off.y
      };
    },
    [mapContentRef, contentOffsetRef, scale]
  );
  const ghostPathD = (0, import_react.useMemo)(() => {
    if (!drawing || !ghostEnd) return null;
    const srcRect = rectsById.get(drawing.fromInstanceId);
    if (!srcRect) return null;
    const sourcePt = (0, import_edgeRouting.getAnchorPoint)(srcRect, drawing.fromAnchor);
    const tgtRect = drawingTarget ? rectsById.get(drawingTarget.instanceId) : null;
    const targetSide = (drawingTarget == null ? void 0 : drawingTarget.anchor) ?? "left";
    const targetPt = tgtRect ? (0, import_edgeRouting.getAnchorPoint)(tgtRect, targetSide) : ghostEnd;
    const points = (0, import_edgeRouting.routeOrthogonal)(
      sourcePt,
      drawing.fromAnchor,
      targetPt,
      targetSide,
      void 0,
      srcRect && tgtRect ? { sourceRect: srcRect, targetRect: tgtRect } : void 0
    );
    return (0, import_edgeRouting.pathFromPoints)(points);
  }, [drawing, ghostEnd, drawingTarget, rectsById]);
  const drawingTargetPreview = (0, import_react.useMemo)(() => {
    if (!drawing || !drawingTarget) return null;
    const rect = rectsById.get(drawingTarget.instanceId);
    if (!rect) return null;
    return {
      instanceId: drawingTarget.instanceId,
      rect,
      anchor: drawingTarget.anchor
    };
  }, [drawing, drawingTarget, rectsById]);
  const startDrawingFromAnchor = (0, import_react.useCallback)(
    (instanceId, anchor) => {
      setDrawing({ fromInstanceId: instanceId, fromAnchor: anchor });
      setDrawingTarget(null);
      setGhostEnd(null);
      setSelectedEdgeId(null);
      setSelectedId(instanceId);
    },
    [setSelectedId]
  );
  const finishDrawing = (0, import_react.useCallback)(
    (clientX, clientY) => {
      if (!drawing || !config) {
        setDrawing(null);
        setGhostEnd(null);
        setDrawingTarget(null);
        return;
      }
      const pt = clientToContent(clientX, clientY);
      if (!pt) {
        setDrawing(null);
        setGhostEnd(null);
        setDrawingTarget(null);
        return;
      }
      const resolved = drawingTarget ?? (0, import_edgeRouting.resolveDrawingTargetAtPoint)(
        pt,
        mergedItems.map((m) => m.id),
        rectsById,
        drawing.fromInstanceId
      );
      const targetId = (resolved == null ? void 0 : resolved.instanceId) ?? null;
      const targetAnchor = resolved == null ? void 0 : resolved.anchor;
      if (targetId && targetId !== drawing.fromInstanceId) {
        const edge = {
          id: newEdgeId(),
          sourceId: drawing.fromInstanceId,
          targetId,
          sourceAnchor: drawing.fromAnchor,
          targetAnchor,
          status: "online"
        };
        commitDraft((prev) => ({
          ...prev,
          edges: [...prev.edges ?? [], edge]
        }));
        setSelectedEdgeId(edge.id);
        setSelectedId(null);
      }
      setDrawing(null);
      setGhostEnd(null);
      setDrawingTarget(null);
    },
    [
      drawing,
      drawingTarget,
      config,
      clientToContent,
      mergedItems,
      rectsById,
      commitDraft,
      setSelectedId
    ]
  );
  (0, import_react.useEffect)(() => {
    if (!drawing) return;
    const onMove = (ev) => {
      const pt = clientToContent(ev.clientX, ev.clientY);
      if (!pt) return;
      const hit = (0, import_edgeRouting.resolveDrawingTargetAtPoint)(
        pt,
        mergedItems.map((m) => m.id),
        rectsById,
        drawing.fromInstanceId
      );
      setDrawingTarget(hit);
      if (hit) {
        const rect = rectsById.get(hit.instanceId);
        if (rect) {
          setGhostEnd((0, import_edgeRouting.getAnchorPoint)(rect, hit.anchor));
          return;
        }
      }
      setGhostEnd(pt);
    };
    const onUp = (ev) => {
      finishDrawing(ev.clientX, ev.clientY);
    };
    window.addEventListener("pointermove", onMove);
    window.addEventListener("pointerup", onUp);
    return () => {
      window.removeEventListener("pointermove", onMove);
      window.removeEventListener("pointerup", onUp);
    };
  }, [drawing, clientToContent, finishDrawing, mergedItems, rectsById]);
  const updateEdge = (0, import_react.useCallback)(
    (edgeId, patch) => {
      commitDraft((prev) => ({
        ...prev,
        edges: (prev.edges ?? []).map(
          (e) => e.id === edgeId ? { ...e, ...patch } : e
        )
      }));
    },
    [commitDraft]
  );
  const draggingSegmentRef = (0, import_react.useRef)(null);
  const startDraggingSegment = (0, import_react.useCallback)(
    (params2) => {
      const edge = edges.find((e) => e.id === params2.edgeId);
      if (!edge) return;
      const currentRoute = routes.find((r) => r.edgeId === params2.edgeId);
      if (!currentRoute) return;
      const baseSnapshot = (0, import_edgeRouting.simplifyCollinearPath)(
        currentRoute.points
      );
      let workingSnapshot = baseSnapshot;
      let targetSegIndex;
      if (params2.role === "first") {
        const srcRect = rectsById.get(edge.sourceId);
        const tgtRect = rectsById.get(edge.targetId);
        const sourceAnchor = edge.sourceAnchor ?? (srcRect && tgtRect ? (0, import_edgeRouting.pickAutoAnchor)(srcRect, tgtRect) : "right");
        const segLen = params2.segmentLength ?? import_edgeRouting.DEFAULT_EDGE_STUB_LENGTH * 2;
        const stubLen = Math.min(import_edgeRouting.DEFAULT_EDGE_STUB_LENGTH, segLen / 2);
        workingSnapshot = (0, import_edgeRouting.applySourceStub)(
          baseSnapshot,
          stubLen,
          sourceAnchor
        );
        targetSegIndex = 2;
      } else if (params2.role === "last") {
        const srcRect = rectsById.get(edge.sourceId);
        const tgtRect = rectsById.get(edge.targetId);
        const targetAnchor = edge.targetAnchor ?? (srcRect && tgtRect ? (0, import_edgeRouting.pickAutoAnchor)(tgtRect, srcRect) : "left");
        const segLen = params2.segmentLength ?? import_edgeRouting.DEFAULT_EDGE_STUB_LENGTH * 2;
        const stubLen = Math.min(import_edgeRouting.DEFAULT_EDGE_STUB_LENGTH, segLen / 2);
        workingSnapshot = (0, import_edgeRouting.applyTargetStub)(
          baseSnapshot,
          stubLen,
          targetAnchor
        );
        targetSegIndex = workingSnapshot.length - 4;
      } else {
        targetSegIndex = params2.segmentIndex;
      }
      draggingSegmentRef.current = {
        edgeId: params2.edgeId,
        workingSnapshot,
        targetSegIndex,
        axis: params2.axis,
        startClientX: params2.clientX,
        startClientY: params2.clientY,
        startPosition: params2.startPosition
      };
      setPendingRoutingByEdge((prev) => ({
        ...prev,
        [params2.edgeId]: { pathSnapshot: workingSnapshot }
      }));
      setSelectedEdgeId(params2.edgeId);
    },
    [edges, routes, rectsById]
  );
  (0, import_react.useEffect)(() => {
    const onMove = (ev) => {
      const drag = draggingSegmentRef.current;
      if (!drag) return;
      const dx = (ev.clientX - drag.startClientX) / scale;
      const dy = (ev.clientY - drag.startClientY) / scale;
      const delta = drag.axis === "h" ? dy : dx;
      const nextPos = drag.startPosition + delta;
      const snap = drag.workingSnapshot.map((p) => [p[0], p[1]]);
      const i = drag.targetSegIndex;
      if (i < 0 || i + 1 >= snap.length) return;
      if (drag.axis === "h") {
        snap[i] = [snap[i][0], nextPos];
        snap[i + 1] = [snap[i + 1][0], nextPos];
      } else {
        snap[i] = [nextPos, snap[i][1]];
        snap[i + 1] = [nextPos, snap[i + 1][1]];
      }
      setPendingRoutingByEdge((prev) => ({
        ...prev,
        [drag.edgeId]: { pathSnapshot: snap }
      }));
    };
    const onUp = () => {
      const drag = draggingSegmentRef.current;
      draggingSegmentRef.current = null;
      if (!drag) return;
      setPendingRoutingByEdge((prev) => {
        const next = { ...prev };
        const finalRouting = next[drag.edgeId];
        delete next[drag.edgeId];
        if (finalRouting) {
          updateEdge(drag.edgeId, { routing: finalRouting });
        }
        return next;
      });
    };
    window.addEventListener("pointermove", onMove);
    window.addEventListener("pointerup", onUp);
    return () => {
      window.removeEventListener("pointermove", onMove);
      window.removeEventListener("pointerup", onUp);
    };
  }, [scale, updateEdge]);
  const deleteEdge = (0, import_react.useCallback)(
    (edgeId) => {
      commitDraft((prev) => ({
        ...prev,
        edges: (prev.edges ?? []).filter((e) => e.id !== edgeId)
      }));
      setSelectedEdgeId((id) => id === edgeId ? null : id);
    },
    [commitDraft]
  );
  const handleEdgeClick = (0, import_react.useCallback)(
    (edgeId) => {
      selectEdge(edgeId);
    },
    [selectEdge]
  );
  const handleMapBackgroundClick = (0, import_react.useCallback)(() => {
    if (drawing) return;
    setSelectedEdgeId(null);
    setSelectedId(null);
  }, [drawing, setSelectedId]);
  (0, import_react.useEffect)(() => {
    if (!enabled) return;
    const onKey = (ev) => {
      if (ev.key !== "Delete" && ev.key !== "Backspace") return;
      if (!selectedEdgeId) return;
      const t = ev.target;
      if (t && (t.tagName === "INPUT" || t.tagName === "TEXTAREA" || t.isContentEditable)) {
        return;
      }
      ev.preventDefault();
      deleteEdge(selectedEdgeId);
    };
    window.addEventListener("keydown", onKey);
    return () => window.removeEventListener("keydown", onKey);
  }, [enabled, selectedEdgeId, deleteEdge]);
  const selectedEdge = (0, import_react.useMemo)(
    () => edges.find((e) => e.id === selectedEdgeId) ?? null,
    [edges, selectedEdgeId]
  );
  const selectedNodeRect = selectedId ? rectsById.get(selectedId) ?? null : null;
  return {
    edges,
    routes,
    rectsById,
    selectedEdgeId,
    selectedEdge,
    selectedNodeRect,
    drawing,
    drawingTargetPreview,
    ghostPathD,
    selectNode,
    selectEdge,
    clearEdgeSelection,
    startDrawingFromAnchor,
    handleEdgeClick,
    handleMapBackgroundClick,
    updateEdge,
    deleteEdge,
    setPendingRectsById,
    startDraggingSegment
  };
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
  useFloorMapEdgeEditing
});
