'use client';
"use client";
import {
  createHoverHandlers
} from "./chunk-BQJWOK4C.mjs";
import "./chunk-HNZOXH4L.mjs";
import "./chunk-D4GAAQMM.mjs";

// src/components/pdf-annotation/PdfAnnotationCanvas.tsx
import { useRef, useState, useCallback, useEffect, useMemo } from "react";
import { getTargetSelector } from "@semiont/api-client";

// src/lib/pdf-coordinates.ts
function canvasToPdfCoordinates(canvasRect, page, _pageWidth, pageHeight, scale = 1) {
  const x1 = Math.min(canvasRect.startX, canvasRect.endX);
  const y1 = Math.min(canvasRect.startY, canvasRect.endY);
  const x2 = Math.max(canvasRect.startX, canvasRect.endX);
  const y2 = Math.max(canvasRect.startY, canvasRect.endY);
  const pdfX = x1 / scale;
  const pdfWidth = (x2 - x1) / scale;
  const pdfY = pageHeight - y2 / scale;
  const pdfHeight = (y2 - y1) / scale;
  return {
    page,
    x: Math.round(pdfX),
    y: Math.round(pdfY),
    width: Math.round(pdfWidth),
    height: Math.round(pdfHeight)
  };
}
function pdfToCanvasCoordinates(pdfCoord, pageHeight, scale = 1) {
  const canvasX = pdfCoord.x * scale;
  const canvasWidth = pdfCoord.width * scale;
  const canvasY = (pageHeight - pdfCoord.y - pdfCoord.height) * scale;
  const canvasHeight = pdfCoord.height * scale;
  return {
    x: canvasX,
    y: canvasY,
    width: canvasWidth,
    height: canvasHeight
  };
}
function createFragmentSelector(coord) {
  return `page=${coord.page}&viewrect=${coord.x},${coord.y},${coord.width},${coord.height}`;
}
function parseFragmentSelector(fragment) {
  try {
    const pageMatch = fragment.match(/page=(\d+)/);
    if (!pageMatch) return null;
    const page = parseInt(pageMatch[1], 10);
    const viewrectMatch = fragment.match(/viewrect=([\d.]+),([\d.]+),([\d.]+),([\d.]+)/);
    if (!viewrectMatch) return null;
    return {
      page,
      x: parseFloat(viewrectMatch[1]),
      y: parseFloat(viewrectMatch[2]),
      width: parseFloat(viewrectMatch[3]),
      height: parseFloat(viewrectMatch[4])
    };
  } catch {
    return null;
  }
}
function getPageFromFragment(fragment) {
  const match = fragment.match(/page=(\d+)/);
  return match ? parseInt(match[1], 10) : null;
}

// src/lib/browser-pdfjs.ts
async function ensurePdfJs() {
  if (typeof window !== "undefined" && window.pdfjsLib) {
    return window.pdfjsLib;
  }
  return new Promise((resolve, reject) => {
    const script = document.createElement("script");
    script.src = "/pdfjs/pdf.min.mjs";
    script.type = "module";
    script.onload = () => {
      const pdfjsLib = window.pdfjsLib;
      if (!pdfjsLib) {
        reject(new Error("PDF.js loaded but pdfjsLib not available"));
        return;
      }
      pdfjsLib.GlobalWorkerOptions.workerSrc = "/pdfjs/pdf.worker.min.mjs";
      resolve(pdfjsLib);
    };
    script.onerror = () => {
      reject(new Error("Failed to load PDF.js from /pdfjs/pdf.min.mjs"));
    };
    document.head.appendChild(script);
  });
}
async function loadPdfDocument(url) {
  const pdfjsLib = await ensurePdfJs();
  const loadingTask = pdfjsLib.getDocument({ url });
  return loadingTask.promise;
}
async function renderPdfPageToDataUrl(page, scale = 1) {
  const viewport = page.getViewport({ scale });
  const canvas = document.createElement("canvas");
  const context = canvas.getContext("2d");
  if (!context) {
    throw new Error("Failed to get 2D context");
  }
  canvas.width = viewport.width;
  canvas.height = viewport.height;
  const renderTask = page.render({
    canvasContext: context,
    viewport
  });
  await renderTask.promise;
  return {
    dataUrl: canvas.toDataURL("image/png"),
    width: viewport.width,
    height: viewport.height
  };
}

// src/components/pdf-annotation/PdfAnnotationCanvas.tsx
import { jsx, jsxs } from "react/jsx-runtime";
function getMotivationColor(motivation) {
  if (!motivation) {
    return { stroke: "rgb(156, 163, 175)", fill: "rgba(156, 163, 175, 0.2)" };
  }
  switch (motivation) {
    case "highlighting":
      return { stroke: "rgb(250, 204, 21)", fill: "rgba(250, 204, 21, 0.3)" };
    case "linking":
      return { stroke: "rgb(59, 130, 246)", fill: "rgba(59, 130, 246, 0.2)" };
    case "assessing":
      return { stroke: "rgb(239, 68, 68)", fill: "rgba(239, 68, 68, 0.2)" };
    case "commenting":
      return { stroke: "rgb(255, 255, 255)", fill: "rgba(255, 255, 255, 0.2)" };
    default:
      return { stroke: "rgb(156, 163, 175)", fill: "rgba(156, 163, 175, 0.2)" };
  }
}
function PdfAnnotationCanvas({
  pdfUrl,
  existingAnnotations = [],
  drawingMode,
  selectedMotivation,
  eventBus,
  hoveredAnnotationId,
  selectedAnnotationId,
  hoverDelayMs = 150
}) {
  const [pdfDoc, setPdfDoc] = useState(null);
  const [numPages, setNumPages] = useState(0);
  const [pageNumber, setPageNumber] = useState(1);
  const [pageImageUrl, setPageImageUrl] = useState(null);
  const [isLoading, setIsLoading] = useState(true);
  const [error, setError] = useState(null);
  const [pageDimensions, setPageDimensions] = useState(null);
  const [displayDimensions, setDisplayDimensions] = useState(null);
  const [scale] = useState(1.5);
  const [isDrawing, setIsDrawing] = useState(false);
  const [selection, setSelection] = useState(null);
  const containerRef = useRef(null);
  const imageRef = useRef(null);
  useEffect(() => {
    let cancelled = false;
    async function loadPdf() {
      try {
        setIsLoading(true);
        setError(null);
        const doc = await loadPdfDocument(pdfUrl);
        if (cancelled) return;
        setPdfDoc(doc);
        setNumPages(doc.numPages);
        setIsLoading(false);
      } catch (err) {
        if (cancelled) return;
        console.error("Error loading PDF:", err);
        setError("Failed to load PDF");
        setIsLoading(false);
      }
    }
    loadPdf();
    return () => {
      cancelled = true;
    };
  }, [pdfUrl]);
  useEffect(() => {
    if (!pdfDoc) return;
    let cancelled = false;
    const doc = pdfDoc;
    async function loadPage() {
      try {
        const page = await doc.getPage(pageNumber);
        if (cancelled) return;
        const viewport = page.getViewport({ scale: 1 });
        setPageDimensions({
          width: viewport.width,
          height: viewport.height
        });
        const { dataUrl } = await renderPdfPageToDataUrl(page, scale);
        if (cancelled) return;
        setPageImageUrl(dataUrl);
      } catch (err) {
        if (cancelled) return;
        console.error("Error loading page:", err);
        setError("Failed to load page");
      }
    }
    loadPage();
    return () => {
      cancelled = true;
    };
  }, [pdfDoc, pageNumber, scale]);
  useEffect(() => {
    const updateDisplayDimensions = () => {
      if (imageRef.current) {
        setDisplayDimensions({
          width: imageRef.current.clientWidth,
          height: imageRef.current.clientHeight
        });
      }
    };
    updateDisplayDimensions();
    let resizeObserver = null;
    try {
      resizeObserver = new ResizeObserver(updateDisplayDimensions);
      if (imageRef.current) {
        resizeObserver.observe(imageRef.current);
      }
    } catch (error2) {
      console.warn("ResizeObserver not supported, falling back to window resize listener");
      window.addEventListener("resize", updateDisplayDimensions);
    }
    return () => {
      if (resizeObserver) {
        resizeObserver.disconnect();
      } else {
        window.removeEventListener("resize", updateDisplayDimensions);
      }
    };
  }, [pageImageUrl]);
  const handleMouseDown = useCallback((e) => {
    if (!drawingMode) return;
    if (!imageRef.current) return;
    const rect = imageRef.current.getBoundingClientRect();
    const x = e.clientX - rect.left;
    const y = e.clientY - rect.top;
    setIsDrawing(true);
    setSelection({
      startX: x,
      startY: y,
      endX: x,
      endY: y
    });
  }, [drawingMode]);
  const handleMouseMove = useCallback((e) => {
    if (!isDrawing || !selection || !imageRef.current) return;
    const rect = imageRef.current.getBoundingClientRect();
    setSelection({
      ...selection,
      endX: e.clientX - rect.left,
      endY: e.clientY - rect.top
    });
  }, [isDrawing, selection]);
  const handleMouseUp = useCallback(() => {
    if (!isDrawing || !selection || !pageDimensions || !displayDimensions || !eventBus) {
      setIsDrawing(false);
      setSelection(null);
      return;
    }
    const dragDistance = Math.sqrt(
      Math.pow(selection.endX - selection.startX, 2) + Math.pow(selection.endY - selection.startY, 2)
    );
    const MIN_DRAG_DISTANCE = 10;
    if (dragDistance < MIN_DRAG_DISTANCE) {
      if (existingAnnotations.length > 0) {
        const clickedAnnotation = pageAnnotations.find((ann) => {
          const fragmentSel = getFragmentSelector(ann.target);
          if (!fragmentSel) return false;
          const pdfCoord2 = parseFragmentSelector(fragmentSel.value);
          if (!pdfCoord2) return false;
          const rect = pdfToCanvasCoordinates(pdfCoord2, pageDimensions.height, 1);
          const scaleX2 = displayDimensions.width / pageDimensions.width;
          const scaleY2 = displayDimensions.height / pageDimensions.height;
          const displayX = rect.x * scaleX2;
          const displayY = rect.y * scaleY2;
          const displayWidth = rect.width * scaleX2;
          const displayHeight = rect.height * scaleY2;
          return selection.endX >= displayX && selection.endX <= displayX + displayWidth && selection.endY >= displayY && selection.endY <= displayY + displayHeight;
        });
        if (clickedAnnotation) {
          eventBus?.get("browse:click").next({ annotationId: clickedAnnotation.id, motivation: clickedAnnotation.motivation });
          setIsDrawing(false);
          setSelection(null);
          return;
        }
      }
      setIsDrawing(false);
      setSelection(null);
      return;
    }
    const scaleX = pageDimensions.width / displayDimensions.width;
    const scaleY = pageDimensions.height / displayDimensions.height;
    const nativeSelection = {
      startX: selection.startX * scaleX,
      startY: selection.startY * scaleY,
      endX: selection.endX * scaleX,
      endY: selection.endY * scaleY
    };
    const pdfCoord = canvasToPdfCoordinates(
      nativeSelection,
      pageNumber,
      pageDimensions.width,
      pageDimensions.height,
      1
      // Use scale 1.0 since we already scaled to native coords
    );
    const fragmentSelector = createFragmentSelector(pdfCoord);
    if (selectedMotivation) {
      eventBus.get("mark:requested").next({
        selector: {
          type: "FragmentSelector",
          conformsTo: "http://tools.ietf.org/rfc/rfc3778",
          value: fragmentSelector
        },
        motivation: selectedMotivation
      });
    }
    setIsDrawing(false);
  }, [isDrawing, selection, pageNumber, pageDimensions, displayDimensions, selectedMotivation, existingAnnotations]);
  const getFragmentSelector = (target) => {
    const selector = getTargetSelector(target);
    if (!selector) return null;
    const selectors = Array.isArray(selector) ? selector : [selector];
    const found = selectors.find((s) => s.type === "FragmentSelector");
    if (!found || found.type !== "FragmentSelector") return null;
    return found;
  };
  const pageAnnotations = existingAnnotations.filter((ann) => {
    const fragmentSel = getFragmentSelector(ann.target);
    if (!fragmentSel) return false;
    const page = getPageFromFragment(fragmentSel.value);
    return page === pageNumber;
  });
  const { handleMouseEnter, handleMouseLeave } = useMemo(
    () => createHoverHandlers((annotationId) => eventBus?.get("beckon:hover").next({ annotationId }), hoverDelayMs),
    [eventBus, hoverDelayMs]
  );
  const { stroke, fill } = getMotivationColor(selectedMotivation ?? null);
  if (error) {
    return /* @__PURE__ */ jsx("div", { className: "semiont-pdf-annotation-canvas__error", children: error });
  }
  return /* @__PURE__ */ jsxs("div", { className: "semiont-pdf-annotation-canvas", children: [
    isLoading && /* @__PURE__ */ jsx("div", { className: "semiont-pdf-annotation-canvas__loading", children: "Loading PDF..." }),
    /* @__PURE__ */ jsxs(
      "div",
      {
        ref: containerRef,
        className: "semiont-pdf-annotation-canvas__container",
        style: { display: isLoading ? "none" : void 0 },
        onMouseDown: handleMouseDown,
        onMouseMove: handleMouseMove,
        onMouseUp: handleMouseUp,
        onMouseLeave: () => {
          if (isDrawing) {
            setIsDrawing(false);
            setSelection(null);
          }
        },
        "data-drawing-mode": drawingMode || "none",
        children: [
          pageImageUrl && /* @__PURE__ */ jsx(
            "img",
            {
              ref: imageRef,
              src: pageImageUrl,
              alt: `PDF page ${pageNumber}`,
              className: "semiont-pdf-annotation-canvas__image",
              draggable: false,
              style: { pointerEvents: "none" },
              onLoad: () => {
                requestAnimationFrame(() => {
                  requestAnimationFrame(() => {
                    if (imageRef.current) {
                      setDisplayDimensions({
                        width: imageRef.current.clientWidth,
                        height: imageRef.current.clientHeight
                      });
                    }
                  });
                });
              }
            }
          ),
          displayDimensions && pageDimensions && /* @__PURE__ */ jsx("div", { className: "semiont-pdf-annotation-canvas__overlay-container", children: /* @__PURE__ */ jsx("div", { className: "semiont-pdf-annotation-canvas__overlay", children: /* @__PURE__ */ jsxs(
            "svg",
            {
              className: "semiont-pdf-annotation-canvas__svg",
              width: displayDimensions.width,
              height: displayDimensions.height,
              children: [
                pageAnnotations.map((ann) => {
                  const fragmentSel = getFragmentSelector(ann.target);
                  if (!fragmentSel) return null;
                  const pdfCoord = parseFragmentSelector(fragmentSel.value);
                  if (!pdfCoord) return null;
                  const rect = pdfToCanvasCoordinates(pdfCoord, pageDimensions.height, 1);
                  const scaleX = displayDimensions.width / pageDimensions.width;
                  const scaleY = displayDimensions.height / pageDimensions.height;
                  const isHovered = ann.id === hoveredAnnotationId;
                  const isSelected = ann.id === selectedAnnotationId;
                  const annMotivation = ann.motivation;
                  const { stroke: annStroke, fill: annFill } = getMotivationColor(annMotivation);
                  return /* @__PURE__ */ jsx(
                    "rect",
                    {
                      x: rect.x * scaleX,
                      y: rect.y * scaleY,
                      width: rect.width * scaleX,
                      height: rect.height * scaleY,
                      stroke: annStroke,
                      strokeWidth: isSelected ? 4 : isHovered ? 3 : 2,
                      fill: annFill,
                      style: {
                        pointerEvents: "auto",
                        cursor: "pointer",
                        opacity: isSelected ? 1 : isHovered ? 0.9 : 0.7
                      },
                      onClick: () => eventBus?.get("browse:click").next({ annotationId: ann.id, motivation: ann.motivation }),
                      onMouseEnter: () => handleMouseEnter(ann.id),
                      onMouseLeave: handleMouseLeave
                    },
                    ann.id
                  );
                }),
                selection && (() => {
                  const rectX = Math.min(selection.startX, selection.endX);
                  const rectY = Math.min(selection.startY, selection.endY);
                  const rectWidth = Math.abs(selection.endX - selection.startX);
                  const rectHeight = Math.abs(selection.endY - selection.startY);
                  return /* @__PURE__ */ jsx(
                    "rect",
                    {
                      x: rectX,
                      y: rectY,
                      width: rectWidth,
                      height: rectHeight,
                      stroke,
                      strokeWidth: 2,
                      strokeDasharray: "5,5",
                      fill,
                      pointerEvents: "none"
                    }
                  );
                })()
              ]
            }
          ) }) })
        ]
      }
    ),
    numPages > 0 && /* @__PURE__ */ jsxs("div", { className: "semiont-pdf-annotation-canvas__controls", children: [
      /* @__PURE__ */ jsx(
        "button",
        {
          disabled: pageNumber <= 1,
          onClick: () => setPageNumber(pageNumber - 1),
          className: "semiont-pdf-annotation-canvas__button",
          children: "Previous"
        }
      ),
      /* @__PURE__ */ jsxs("span", { className: "semiont-pdf-annotation-canvas__page-info", children: [
        "Page ",
        pageNumber,
        " of ",
        numPages
      ] }),
      /* @__PURE__ */ jsx(
        "button",
        {
          disabled: pageNumber >= numPages,
          onClick: () => setPageNumber(pageNumber + 1),
          className: "semiont-pdf-annotation-canvas__button",
          children: "Next"
        }
      )
    ] })
  ] });
}
export {
  PdfAnnotationCanvas
};
//# sourceMappingURL=PdfAnnotationCanvas.client-CW6SKH2U.mjs.map