"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 Translating_exports = {};
__export(Translating_exports, {
  Translating: () => Translating,
  moveShapesToPoint: () => moveShapesToPoint
});
module.exports = __toCommonJS(Translating_exports);
var import_editor = require("@cmpd/editor");
var import_DragAndDropManager = require("../DragAndDropManager");
class Translating extends import_editor.StateNode {
  static id = "translating";
  info = {};
  selectionSnapshot = {};
  snapshot = {};
  markId = "";
  isCloning = false;
  isCreating = false;
  onCreate = () => void 0;
  dragAndDropManager = new import_DragAndDropManager.DragAndDropManager(this.editor);
  onEnter = (info) => {
    const { isCreating = false, onCreate = () => void 0 } = info;
    this.info = info;
    this.parent.setCurrentToolIdMask(info.onInteractionEnd);
    this.isCreating = isCreating;
    this.onCreate = onCreate;
    if (isCreating) {
      this.markId = `creating:${this.editor.getOnlySelectedShape().id}`;
    } else {
      this.markId = "translating";
      this.editor.mark(this.markId);
    }
    this.isCloning = false;
    this.info = info;
    this.editor.setCursor({ type: "move", rotation: 0 });
    this.selectionSnapshot = getTranslatingSnapshot(this.editor);
    if (!this.isCreating) {
      if (this.editor.inputs.altKey) {
        this.startCloning();
        return;
      }
    }
    this.snapshot = this.selectionSnapshot;
    this.handleStart();
    this.updateShapes();
    this.editor.on("tick", this.updateParent);
  };
  onExit = () => {
    this.parent.setCurrentToolIdMask(void 0);
    this.editor.off("tick", this.updateParent);
    this.selectionSnapshot = {};
    this.snapshot = {};
    this.editor.snaps.clear();
    this.editor.updateInstanceState(
      { cursor: { type: "default", rotation: 0 } },
      { ephemeral: true }
    );
    this.dragAndDropManager.clear();
  };
  onPointerMove = () => {
    this.updateShapes();
  };
  onKeyDown = () => {
    if (this.editor.inputs.altKey && !this.isCloning) {
      this.startCloning();
      return;
    }
    this.updateShapes();
  };
  onKeyUp = () => {
    if (!this.editor.inputs.altKey && this.isCloning) {
      this.stopCloning();
      return;
    }
    this.updateShapes();
  };
  onPointerUp = () => {
    this.complete();
  };
  onComplete = () => {
    this.complete();
  };
  onCancel = () => {
    this.cancel();
  };
  startCloning() {
    if (this.isCreating)
      return;
    this.isCloning = true;
    this.reset();
    this.markId = "translating";
    this.editor.mark(this.markId);
    this.editor.duplicateShapes(Array.from(this.editor.getSelectedShapeIds()));
    this.snapshot = getTranslatingSnapshot(this.editor);
    this.handleStart();
    this.updateShapes();
  }
  stopCloning() {
    this.isCloning = false;
    this.snapshot = this.selectionSnapshot;
    this.reset();
    this.markId = "translating";
    this.editor.mark(this.markId);
    this.updateShapes();
  }
  updateParent = () => {
    const { snapshot } = this;
    this.dragAndDropManager.updateDroppingNode(snapshot.movingShapes, this.updateParentTransforms);
  };
  reset() {
    this.editor.bailToMark(this.markId);
  }
  complete() {
    this.updateShapes();
    this.dragAndDropManager.dropShapes(this.snapshot.movingShapes);
    this.handleEnd();
    if (this.editor.getInstanceState().isToolLocked && this.info.onInteractionEnd) {
      this.editor.setCurrentTool(this.info.onInteractionEnd);
    } else {
      if (this.isCreating) {
        this.onCreate?.(this.editor.getOnlySelectedShape());
      } else {
        this.parent.transition("idle");
      }
    }
  }
  cancel() {
    this.reset();
    if (this.info.onInteractionEnd) {
      this.editor.setCurrentTool(this.info.onInteractionEnd);
    } else {
      this.parent.transition("idle", this.info);
    }
  }
  handleStart() {
    const { movingShapes } = this.snapshot;
    const changes = [];
    movingShapes.forEach((shape) => {
      const util = this.editor.getShapeUtil(shape);
      const change = util.onTranslateStart?.(shape);
      if (change) {
        changes.push(change);
      }
    });
    if (changes.length > 0) {
      this.editor.updateShapes(changes);
    }
    this.editor.setHoveredShape(null);
  }
  handleEnd() {
    const { movingShapes } = this.snapshot;
    const changes = [];
    movingShapes.forEach((shape) => {
      const current = this.editor.getShape(shape.id);
      const util = this.editor.getShapeUtil(shape);
      const change = util.onTranslateEnd?.(shape, current);
      if (change) {
        changes.push(change);
      }
    });
    if (changes.length > 0) {
      this.editor.updateShapes(changes);
    }
  }
  handleChange() {
    const { movingShapes } = this.snapshot;
    const changes = [];
    movingShapes.forEach((shape) => {
      const current = this.editor.getShape(shape.id);
      const util = this.editor.getShapeUtil(shape);
      const change = util.onTranslate?.(shape, current);
      if (change) {
        changes.push(change);
      }
    });
    if (changes.length > 0) {
      this.editor.updateShapes(changes);
    }
  }
  updateShapes() {
    const { snapshot } = this;
    this.dragAndDropManager.updateDroppingNode(snapshot.movingShapes, this.updateParentTransforms);
    moveShapesToPoint({
      editor: this.editor,
      shapeSnapshots: snapshot.shapeSnapshots,
      averagePagePoint: snapshot.averagePagePoint,
      initialSelectionPageBounds: snapshot.initialPageBounds,
      initialSelectionSnapPoints: snapshot.initialSnapPoints
    });
    this.handleChange();
  }
  updateParentTransforms = () => {
    const {
      editor,
      snapshot: { shapeSnapshots }
    } = this;
    const movingShapes = [];
    shapeSnapshots.forEach((shapeSnapshot) => {
      const shape = editor.getShape(shapeSnapshot.shape.id);
      if (!shape)
        return null;
      movingShapes.push(shape);
      const parentTransform = (0, import_editor.isPageId)(shape.parentId) ? null : import_editor.Matrix2d.Inverse(editor.getShapePageTransform(shape.parentId));
      shapeSnapshot.parentTransform = parentTransform;
    });
  };
}
function getTranslatingSnapshot(editor) {
  const movingShapes = [];
  const pagePoints = [];
  const shapeSnapshots = (0, import_editor.compact)(
    editor.getSelectedShapeIds().map((id) => {
      const shape = editor.getShape(id);
      if (!shape)
        return null;
      movingShapes.push(shape);
      const pagePoint = editor.getShapePageTransform(id).point();
      if (!pagePoint)
        return null;
      pagePoints.push(pagePoint);
      const parentTransform = import_editor.PageRecordType.isId(shape.parentId) ? null : import_editor.Matrix2d.Inverse(editor.getShapePageTransform(shape.parentId));
      return {
        shape,
        pagePoint,
        parentTransform
      };
    })
  );
  let initialSnapPoints = [];
  if (editor.getSelectedShapeIds().length === 1) {
    initialSnapPoints = editor.snaps.getSnapPointsCache().get(editor.getSelectedShapeIds()[0]);
  } else {
    const selectionPageBounds = editor.getSelectionPageBounds();
    if (selectionPageBounds) {
      initialSnapPoints = selectionPageBounds.snapPoints.map((p, i) => ({
        id: "selection:" + i,
        x: p.x,
        y: p.y
      }));
    }
  }
  return {
    averagePagePoint: import_editor.Vec2d.Average(pagePoints),
    movingShapes,
    shapeSnapshots,
    initialPageBounds: editor.getSelectionPageBounds(),
    initialSnapPoints
  };
}
function moveShapesToPoint({
  editor,
  shapeSnapshots: snapshots,
  averagePagePoint,
  initialSelectionPageBounds,
  initialSelectionSnapPoints
}) {
  const { inputs } = editor;
  const isGridMode = editor.getInstanceState().isGridMode;
  const gridSize = editor.getDocumentSettings().gridSize;
  const delta = import_editor.Vec2d.Sub(inputs.currentPagePoint, inputs.originPagePoint);
  const flatten = editor.inputs.shiftKey ? Math.abs(delta.x) < Math.abs(delta.y) ? "x" : "y" : null;
  if (flatten === "x") {
    delta.x = 0;
  } else if (flatten === "y") {
    delta.y = 0;
  }
  editor.snaps.clear();
  const shouldSnap = (editor.user.getIsSnapMode() ? !inputs.ctrlKey : inputs.ctrlKey) && editor.inputs.pointerVelocity.len() < 0.5;
  if (shouldSnap) {
    const { nudge } = editor.snaps.snapTranslate({
      dragDelta: delta,
      initialSelectionPageBounds,
      lockedAxis: flatten,
      initialSelectionSnapPoints
    });
    delta.add(nudge);
  }
  const averageSnappedPoint = import_editor.Vec2d.Add(averagePagePoint, delta);
  if (isGridMode && !inputs.ctrlKey) {
    averageSnappedPoint.snapToGrid(gridSize);
  }
  const averageSnap = import_editor.Vec2d.Sub(averageSnappedPoint, averagePagePoint);
  editor.updateShapes(
    (0, import_editor.compact)(
      snapshots.map(({ shape, pagePoint, parentTransform }) => {
        const newPagePoint = import_editor.Vec2d.Add(pagePoint, averageSnap);
        const newLocalPoint = parentTransform ? import_editor.Matrix2d.applyToPoint(parentTransform, newPagePoint) : newPagePoint;
        return {
          id: shape.id,
          type: shape.type,
          x: newLocalPoint.x,
          y: newLocalPoint.y
        };
      })
    ),
    { squashing: true }
  );
}
//# sourceMappingURL=Translating.js.map
