import { Fragment, jsx, jsxs } from "react/jsx-runtime";
import {
  Box,
  Circle2d,
  Polygon2d,
  Polyline2d,
  SVGContainer,
  ShapeUtil,
  drawShapeMigrations,
  drawShapeProps,
  getColorValue,
  last,
  lerp,
  rng,
  useEditor,
  useValue
} from "@tldraw/editor";
import { ShapeFill } from "../shared/ShapeFill.mjs";
import { STROKE_SIZES } from "../shared/default-shape-constants.mjs";
import { getFillDefForCanvas, getFillDefForExport } from "../shared/defaultStyleDefs.mjs";
import { getStrokePoints } from "../shared/freehand/getStrokePoints.mjs";
import { getSvgPathFromStrokePoints } from "../shared/freehand/svg.mjs";
import { svgInk } from "../shared/freehand/svgInk.mjs";
import { interpolateSegments } from "../shared/interpolate-props.mjs";
import { useDefaultColorTheme } from "../shared/useDefaultColorTheme.mjs";
import {
  getDrawShapeStrokeDashArray,
  getFreehandOptions,
  getPointsFromDrawSegments
} from "./getPath.mjs";
class DrawShapeUtil extends ShapeUtil {
  static type = "draw";
  static props = drawShapeProps;
  static migrations = drawShapeMigrations;
  options = {
    maxPointsPerShape: 600
  };
  hideResizeHandles(shape) {
    return getIsDot(shape);
  }
  hideRotateHandle(shape) {
    return getIsDot(shape);
  }
  hideSelectionBoundsFg(shape) {
    return getIsDot(shape);
  }
  getDefaultProps() {
    return {
      segments: [],
      color: "black",
      fill: "none",
      dash: "draw",
      size: "m",
      isComplete: false,
      isClosed: false,
      isPen: false,
      scale: 1,
      scaleX: 1,
      scaleY: 1
    };
  }
  getGeometry(shape) {
    const points = getPointsFromDrawSegments(
      shape.props.segments,
      shape.props.scaleX,
      shape.props.scaleY
    );
    const sw = (STROKE_SIZES[shape.props.size] + 1) * shape.props.scale;
    if (shape.props.segments.length === 1) {
      const box = Box.FromPoints(points);
      if (box.width < sw * 2 && box.height < sw * 2) {
        return new Circle2d({
          x: -sw,
          y: -sw,
          radius: sw,
          isFilled: true
        });
      }
    }
    const strokePoints = getStrokePoints(
      points,
      getFreehandOptions(shape.props, sw, shape.props.isPen, true)
    ).map((p) => p.point);
    if (shape.props.isClosed && strokePoints.length > 2) {
      return new Polygon2d({
        points: strokePoints,
        isFilled: shape.props.fill !== "none"
      });
    }
    if (strokePoints.length === 1) {
      return new Circle2d({
        x: -sw,
        y: -sw,
        radius: sw,
        isFilled: true
      });
    }
    return new Polyline2d({
      points: strokePoints
    });
  }
  component(shape) {
    return /* @__PURE__ */ jsx(SVGContainer, { children: /* @__PURE__ */ jsx(DrawShapeSvg, { shape }) });
  }
  indicator(shape) {
    const allPointsFromSegments = getPointsFromDrawSegments(
      shape.props.segments,
      shape.props.scaleX,
      shape.props.scaleY
    );
    let sw = (STROKE_SIZES[shape.props.size] + 1) * shape.props.scale;
    const forceSolid = useValue(
      "force solid",
      () => {
        const zoomLevel = this.editor.getEfficientZoomLevel();
        return zoomLevel < 0.5 && zoomLevel < 1.5 / sw;
      },
      [this.editor, sw]
    );
    if (!forceSolid && !shape.props.isPen && shape.props.dash === "draw" && allPointsFromSegments.length === 1) {
      sw += rng(shape.id)() * (sw / 6);
    }
    const showAsComplete = shape.props.isComplete || last(shape.props.segments)?.type === "straight";
    const options = getFreehandOptions(shape.props, sw, showAsComplete, true);
    const strokePoints = getStrokePoints(allPointsFromSegments, options);
    const solidStrokePath = strokePoints.length > 1 ? getSvgPathFromStrokePoints(strokePoints, shape.props.isClosed) : getDot(allPointsFromSegments[0], sw);
    return /* @__PURE__ */ jsx("path", { d: solidStrokePath });
  }
  toSvg(shape, ctx) {
    ctx.addExportDef(getFillDefForExport(shape.props.fill));
    const scaleFactor = 1 / shape.props.scale;
    return /* @__PURE__ */ jsx("g", { transform: `scale(${scaleFactor})`, children: /* @__PURE__ */ jsx(DrawShapeSvg, { shape, zoomOverride: 1 }) });
  }
  getCanvasSvgDefs() {
    return [getFillDefForCanvas()];
  }
  onResize(shape, info) {
    const { scaleX, scaleY } = info;
    return {
      props: {
        scaleX: scaleX * shape.props.scaleX,
        scaleY: scaleY * shape.props.scaleY
      }
    };
  }
  expandSelectionOutlinePx(shape) {
    const multiplier = shape.props.dash === "draw" ? 1.6 : 1;
    return STROKE_SIZES[shape.props.size] * multiplier / 2 * shape.props.scale;
  }
  getInterpolatedProps(startShape, endShape, t) {
    return {
      ...(t > 0.5 ? endShape.props : startShape.props),
      segments: interpolateSegments(startShape.props.segments, endShape.props.segments, t),
      scale: lerp(startShape.props.scale, endShape.props.scale, t)
    };
  }
}
function getDot(point, sw) {
  const r = (sw + 1) * 0.5;
  return `M ${point.x} ${point.y} m -${r}, 0 a ${r},${r} 0 1,0 ${r * 2},0 a ${r},${r} 0 1,0 -${r * 2},0`;
}
function getIsDot(shape) {
  return shape.props.segments.length === 1 && shape.props.segments[0].points.length < 16;
}
function DrawShapeSvg({ shape, zoomOverride }) {
  const theme = useDefaultColorTheme();
  const editor = useEditor();
  const allPointsFromSegments = getPointsFromDrawSegments(
    shape.props.segments,
    shape.props.scaleX,
    shape.props.scaleY
  );
  const showAsComplete = shape.props.isComplete || last(shape.props.segments)?.type === "straight";
  let sw = (STROKE_SIZES[shape.props.size] + 1) * shape.props.scale;
  const forceSolid = useValue(
    "force solid",
    () => {
      const zoomLevel = zoomOverride ?? editor.getEfficientZoomLevel();
      return zoomLevel < 0.5 && zoomLevel < 1.5 / sw;
    },
    [editor, sw, zoomOverride]
  );
  const dotAdjustment = useValue(
    "dot adjustment",
    () => {
      const zoomLevel = zoomOverride ?? editor.getEfficientZoomLevel();
      return zoomLevel < 0.2 ? 0 : 0.1;
    },
    [editor, zoomOverride]
  );
  if (!forceSolid && !shape.props.isPen && shape.props.dash === "draw" && allPointsFromSegments.length === 1) {
    sw += rng(shape.id)() * (sw / 6);
  }
  const options = getFreehandOptions(shape.props, sw, showAsComplete, forceSolid);
  if (!forceSolid && shape.props.dash === "draw") {
    return /* @__PURE__ */ jsxs(Fragment, { children: [
      shape.props.isClosed && shape.props.fill && allPointsFromSegments.length > 1 ? /* @__PURE__ */ jsx(
        ShapeFill,
        {
          d: getSvgPathFromStrokePoints(
            getStrokePoints(allPointsFromSegments, options),
            shape.props.isClosed
          ),
          theme,
          color: shape.props.color,
          fill: shape.props.isClosed ? shape.props.fill : "none",
          scale: shape.props.scale
        }
      ) : null,
      /* @__PURE__ */ jsx(
        "path",
        {
          d: svgInk(allPointsFromSegments, options),
          strokeLinecap: "round",
          fill: getColorValue(theme, shape.props.color, "solid")
        }
      )
    ] });
  }
  const strokePoints = getStrokePoints(allPointsFromSegments, options);
  const isDot = strokePoints.length < 2;
  const solidStrokePath = isDot ? getDot(allPointsFromSegments[0], 0) : getSvgPathFromStrokePoints(strokePoints, shape.props.isClosed);
  return /* @__PURE__ */ jsxs(Fragment, { children: [
    /* @__PURE__ */ jsx(
      ShapeFill,
      {
        d: solidStrokePath,
        theme,
        color: shape.props.color,
        fill: isDot || shape.props.isClosed ? shape.props.fill : "none",
        scale: shape.props.scale
      }
    ),
    /* @__PURE__ */ jsx(
      "path",
      {
        d: solidStrokePath,
        strokeLinecap: "round",
        fill: isDot ? getColorValue(theme, shape.props.color, "solid") : "none",
        stroke: getColorValue(theme, shape.props.color, "solid"),
        strokeWidth: sw,
        strokeDasharray: isDot ? "none" : getDrawShapeStrokeDashArray(shape, sw, dotAdjustment),
        strokeDashoffset: "0"
      }
    )
  ] });
}
export {
  DrawShapeUtil
};
//# sourceMappingURL=DrawShapeUtil.mjs.map
