"use strict";
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);
var cloudOutline_exports = {};
__export(cloudOutline_exports, {
  cloudOutline: () => cloudOutline,
  cloudSvgPath: () => cloudSvgPath,
  getCloudArcs: () => getCloudArcs,
  getPillPoints: () => getPillPoints,
  inkyCloudSvgPath: () => inkyCloudSvgPath,
  pointsOnArc: () => pointsOnArc
});
module.exports = __toCommonJS(cloudOutline_exports);
var import_editor = require("@cmpd/editor");
function getPillCircumference(width, height) {
  const radius = Math.min(width, height) / 2;
  const longSide = Math.max(width, height) - radius * 2;
  return Math.PI * (radius * 2) + 2 * longSide;
}
function getPillPoints(width, height, numPoints) {
  const radius = Math.min(width, height) / 2;
  const longSide = Math.max(width, height) - radius * 2;
  const circumference = Math.PI * (radius * 2) + 2 * longSide;
  const spacing = circumference / numPoints;
  const sections = width > height ? [
    {
      type: "straight",
      start: new import_editor.Vec2d(radius, 0),
      delta: new import_editor.Vec2d(1, 0)
    },
    {
      type: "arc",
      center: new import_editor.Vec2d(width - radius, radius),
      startAngle: -import_editor.PI / 2
    },
    {
      type: "straight",
      start: new import_editor.Vec2d(width - radius, height),
      delta: new import_editor.Vec2d(-1, 0)
    },
    {
      type: "arc",
      center: new import_editor.Vec2d(radius, radius),
      startAngle: import_editor.PI / 2
    }
  ] : [
    {
      type: "straight",
      start: new import_editor.Vec2d(width, radius),
      delta: new import_editor.Vec2d(0, 1)
    },
    {
      type: "arc",
      center: new import_editor.Vec2d(radius, height - radius),
      startAngle: 0
    },
    {
      type: "straight",
      start: new import_editor.Vec2d(0, height - radius),
      delta: new import_editor.Vec2d(0, -1)
    },
    {
      type: "arc",
      center: new import_editor.Vec2d(radius, radius),
      startAngle: import_editor.PI
    }
  ];
  let sectionOffset = 0;
  const points = [];
  for (let i = 0; i < numPoints; i++) {
    const section = sections[0];
    if (section.type === "straight") {
      points.push(import_editor.Vec2d.Add(section.start, import_editor.Vec2d.Mul(section.delta, sectionOffset)));
    } else {
      points.push(
        (0, import_editor.getPointOnCircle)(
          section.center.x,
          section.center.y,
          radius,
          section.startAngle + sectionOffset / radius
        )
      );
    }
    sectionOffset += spacing;
    let sectionLength = section.type === "straight" ? longSide : import_editor.PI * radius;
    while (sectionOffset > sectionLength) {
      sectionOffset -= sectionLength;
      sections.push(sections.shift());
      sectionLength = sections[0].type === "straight" ? longSide : import_editor.PI * radius;
    }
  }
  return points;
}
const switchSize = (size, s, m, l, xl) => {
  switch (size) {
    case "s":
      return s;
    case "m":
      return m;
    case "l":
      return l;
    case "xl":
      return xl;
  }
};
function getCloudArcs(width, height, seed, size) {
  const getRandom = (0, import_editor.rng)(seed);
  const pillCircumference = getPillCircumference(width, height);
  const numBumps = Math.max(
    Math.ceil(pillCircumference / switchSize(size, 50, 70, 100, 130)),
    6,
    Math.ceil(pillCircumference / Math.min(width, height))
  );
  const targetBumpProtrusion = pillCircumference / numBumps * 0.2;
  const innerWidth = Math.max(width - targetBumpProtrusion * 2, 1);
  const innerHeight = Math.max(height - targetBumpProtrusion * 2, 1);
  const paddingX = (width - innerWidth) / 2;
  const paddingY = (height - innerHeight) / 2;
  const distanceBetweenPointsOnPerimeter = getPillCircumference(innerWidth, innerHeight) / numBumps;
  const bumpPoints = getPillPoints(innerWidth, innerHeight, numBumps).map((p) => {
    return p.addXY(paddingX, paddingY);
  });
  const maxWiggleX = width < 20 ? 0 : targetBumpProtrusion * 0.3;
  const maxWiggleY = height < 20 ? 0 : targetBumpProtrusion * 0.3;
  const wiggledPoints = bumpPoints.slice(0);
  for (let i = 0; i < Math.floor(numBumps / 2); i++) {
    wiggledPoints[i] = import_editor.Vec2d.AddXY(
      wiggledPoints[i],
      getRandom() * maxWiggleX,
      getRandom() * maxWiggleY
    );
    wiggledPoints[numBumps - i - 1] = import_editor.Vec2d.AddXY(
      wiggledPoints[numBumps - i - 1],
      getRandom() * maxWiggleX,
      getRandom() * maxWiggleY
    );
  }
  const arcs = [];
  for (let i = 0; i < wiggledPoints.length; i++) {
    const j = i === wiggledPoints.length - 1 ? 0 : i + 1;
    const leftWigglePoint = wiggledPoints[i];
    const rightWigglePoint = wiggledPoints[j];
    const leftPoint = bumpPoints[i];
    const rightPoint = bumpPoints[j];
    const midPoint = import_editor.Vec2d.Average([leftPoint, rightPoint]);
    const offsetAngle = import_editor.Vec2d.Angle(leftPoint, rightPoint) - Math.PI / 2;
    const distanceBetweenOriginalPoints = import_editor.Vec2d.Dist(leftPoint, rightPoint);
    const curvatureOffset = distanceBetweenPointsOnPerimeter - distanceBetweenOriginalPoints;
    const distanceBetweenWigglePoints = import_editor.Vec2d.Dist(leftWigglePoint, rightWigglePoint);
    const relativeSize = distanceBetweenWigglePoints / distanceBetweenOriginalPoints;
    const finalDistance = (Math.max(paddingX, paddingY) + curvatureOffset) * relativeSize;
    const arcPoint = import_editor.Vec2d.Add(midPoint, import_editor.Vec2d.FromAngle(offsetAngle, finalDistance));
    if (arcPoint.x < 0) {
      arcPoint.x = 0;
    } else if (arcPoint.x > width) {
      arcPoint.x = width;
    }
    if (arcPoint.y < 0) {
      arcPoint.y = 0;
    } else if (arcPoint.y > height) {
      arcPoint.y = height;
    }
    const center = getCenterOfCircleGivenThreePoints(leftWigglePoint, rightWigglePoint, arcPoint);
    const radius = import_editor.Vec2d.Dist(
      center ? center : import_editor.Vec2d.Average([leftWigglePoint, rightWigglePoint]),
      leftWigglePoint
    );
    arcs.push({
      leftPoint: leftWigglePoint,
      rightPoint: rightWigglePoint,
      arcPoint,
      center,
      radius
    });
  }
  return arcs;
}
function getCenterOfCircleGivenThreePoints(a, b, c) {
  const A = a.x * (b.y - c.y) - a.y * (b.x - c.x) + b.x * c.y - c.x * b.y;
  const B = (a.x * a.x + a.y * a.y) * (c.y - b.y) + (b.x * b.x + b.y * b.y) * (a.y - c.y) + (c.x * c.x + c.y * c.y) * (b.y - a.y);
  const C = (a.x * a.x + a.y * a.y) * (b.x - c.x) + (b.x * b.x + b.y * b.y) * (c.x - a.x) + (c.x * c.x + c.y * c.y) * (a.x - b.x);
  const x = -B / (2 * A);
  const y = -C / (2 * A);
  if (!Number.isFinite(x) || !Number.isFinite(y)) {
    return null;
  }
  return new import_editor.Vec2d(x, y);
}
function cloudOutline(width, height, seed, size) {
  const path = [];
  const arcs = getCloudArcs(width, height, seed, size);
  for (const { center, radius, leftPoint, rightPoint } of arcs) {
    path.push(...pointsOnArc(leftPoint, rightPoint, center, radius, 10));
  }
  return path;
}
function cloudSvgPath(width, height, seed, size) {
  const arcs = getCloudArcs(width, height, seed, size);
  let path = `M${(0, import_editor.toDomPrecision)(arcs[0].leftPoint.x)},${(0, import_editor.toDomPrecision)(arcs[0].leftPoint.y)}`;
  for (const { leftPoint, rightPoint, radius, center } of arcs) {
    if (center === null) {
      path += ` L${(0, import_editor.toDomPrecision)(rightPoint.x)},${(0, import_editor.toDomPrecision)(rightPoint.y)}`;
      continue;
    }
    const arc = isLeft(leftPoint, rightPoint, center) ? "0" : "1";
    path += ` A${(0, import_editor.toDomPrecision)(radius)},${(0, import_editor.toDomPrecision)(radius)} 0 ${arc},1 ${(0, import_editor.toDomPrecision)(
      rightPoint.x
    )},${(0, import_editor.toDomPrecision)(rightPoint.y)}`;
  }
  path += " Z";
  return path;
}
function inkyCloudSvgPath(width, height, seed, size) {
  const getRandom = (0, import_editor.rng)(seed);
  const mutMultiplier = size === "s" ? 0.5 : size === "m" ? 0.7 : size === "l" ? 0.9 : 1.6;
  const mut = (n) => {
    return n + getRandom() * mutMultiplier * 2;
  };
  const arcs = getCloudArcs(width, height, seed, size);
  const avgArcLength = arcs.reduce((sum, arc) => sum + import_editor.Vec2d.Dist(arc.leftPoint, arc.rightPoint), 0) / arcs.length;
  const shouldMutatePoints = avgArcLength > mutMultiplier * 15;
  const mutPoint = shouldMutatePoints ? (p) => new import_editor.Vec2d(mut(p.x), mut(p.y)) : (p) => p;
  let pathA = `M${(0, import_editor.toDomPrecision)(arcs[0].leftPoint.x)},${(0, import_editor.toDomPrecision)(arcs[0].leftPoint.y)}`;
  let leftMutPoint = mutPoint(arcs[0].leftPoint);
  let pathB = `M${(0, import_editor.toDomPrecision)(leftMutPoint.x)},${(0, import_editor.toDomPrecision)(leftMutPoint.y)}`;
  for (const { leftPoint, center, rightPoint, radius, arcPoint } of arcs) {
    if (center === null) {
      pathA += ` L${(0, import_editor.toDomPrecision)(rightPoint.x)},${(0, import_editor.toDomPrecision)(rightPoint.y)}`;
      const rightMutPoint2 = mutPoint(rightPoint);
      pathB += ` L${(0, import_editor.toDomPrecision)(rightMutPoint2.x)},${(0, import_editor.toDomPrecision)(rightMutPoint2.y)}`;
      leftMutPoint = rightMutPoint2;
      continue;
    }
    const arc = isLeft(leftPoint, rightPoint, center) ? "0" : "1";
    pathA += ` A${(0, import_editor.toDomPrecision)(radius)},${(0, import_editor.toDomPrecision)(radius)} 0 ${arc},1 ${(0, import_editor.toDomPrecision)(
      rightPoint.x
    )},${(0, import_editor.toDomPrecision)(rightPoint.y)}`;
    const rightMutPoint = mutPoint(rightPoint);
    const mutArcPoint = mutPoint(arcPoint);
    const mutCenter = getCenterOfCircleGivenThreePoints(leftMutPoint, rightMutPoint, mutArcPoint);
    if (!mutCenter) {
      pathB += ` L${(0, import_editor.toDomPrecision)(rightMutPoint.x)},${(0, import_editor.toDomPrecision)(rightMutPoint.y)}`;
      leftMutPoint = rightMutPoint;
      continue;
    }
    const mutRadius = Math.abs(import_editor.Vec2d.Dist(mutCenter, leftMutPoint));
    pathB += ` A${(0, import_editor.toDomPrecision)(mutRadius)},${(0, import_editor.toDomPrecision)(
      mutRadius
    )} 0 ${arc},1 ${(0, import_editor.toDomPrecision)(rightMutPoint.x)},${(0, import_editor.toDomPrecision)(rightMutPoint.y)}`;
    leftMutPoint = rightMutPoint;
  }
  return pathA + pathB + " Z";
}
function pointsOnArc(startPoint, endPoint, center, radius, numPoints) {
  if (center === null) {
    return [import_editor.Vec2d.From(startPoint), import_editor.Vec2d.From(endPoint)];
  }
  const results = [];
  const startAngle = import_editor.Vec2d.Angle(center, startPoint);
  const endAngle = import_editor.Vec2d.Angle(center, endPoint);
  const l = (0, import_editor.clockwiseAngleDist)(startAngle, endAngle);
  for (let i = 0; i < numPoints; i++) {
    const t = i / (numPoints - 1);
    const angle = startAngle + l * t;
    const point = (0, import_editor.getPointOnCircle)(center.x, center.y, radius, angle);
    results.push(point);
  }
  return results;
}
function isLeft(a, b, c) {
  return (b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x) > 0;
}
//# sourceMappingURL=cloudOutline.js.map
