import {
  HIT_TEST_MARGIN,
  StateNode,
  Vec2d,
  createShapeId,
  pointInPolygon
} from "@cmpd/editor";
import { getHitShapeOnCanvasPointerDown } from "../../selection-logic/getHitShapeOnCanvasPointerDown.mjs";
import { getShouldEnterCropMode } from "../../selection-logic/getShouldEnterCropModeOnPointerDown.mjs";
import { selectOnCanvasPointerUp } from "../../selection-logic/selectOnCanvasPointerUp.mjs";
import { updateHoveredId } from "../../selection-logic/updateHoveredId.mjs";
class Idle extends StateNode {
  static id = "idle";
  onEnter = () => {
    this.parent.setCurrentToolIdMask(void 0);
    updateHoveredId(this.editor);
    this.editor.updateInstanceState(
      { cursor: { type: "default", rotation: 0 } },
      { ephemeral: true }
    );
  };
  onPointerMove = () => {
    updateHoveredId(this.editor);
  };
  onPointerDown = (info) => {
    if (this.editor.getIsMenuOpen())
      return;
    const shouldEnterCropMode = info.ctrlKey && getShouldEnterCropMode(this.editor);
    if (info.ctrlKey && !shouldEnterCropMode) {
      if (info.target === "shape" && this.isDarwin && this.editor.inputs.keys.has("ControlLeft")) {
        if (!this.editor.isShapeOrAncestorLocked(info.shape)) {
          this.parent.transition("pointing_shape", info);
          return;
        }
      }
      this.parent.transition("brushing", info);
      return;
    }
    switch (info.target) {
      case "canvas": {
        const hitShape = getHitShapeOnCanvasPointerDown(this.editor);
        if (hitShape) {
          this.onPointerDown({
            ...info,
            shape: hitShape,
            target: "shape"
          });
          return;
        }
        const selectedShapeIds = this.editor.getSelectedShapeIds();
        const onlySelectedShape = this.editor.getOnlySelectedShape();
        const {
          inputs: { currentPagePoint }
        } = this.editor;
        if (selectedShapeIds.length > 1 || onlySelectedShape && !this.editor.getShapeUtil(onlySelectedShape).hideSelectionBoundsBg(onlySelectedShape)) {
          if (isPointInRotatedSelectionBounds(this.editor, currentPagePoint)) {
            this.onPointerDown({
              ...info,
              target: "selection"
            });
            return;
          }
        }
        this.parent.transition("pointing_canvas", info);
        break;
      }
      case "shape": {
        if (this.editor.isShapeOrAncestorLocked(info.shape)) {
          this.parent.transition("pointing_canvas", info);
          break;
        }
        this.parent.transition("pointing_shape", info);
        break;
      }
      case "handle": {
        if (this.editor.getInstanceState().isReadonly)
          break;
        if (this.editor.inputs.altKey) {
          this.parent.transition("pointing_shape", info);
        } else {
          this.parent.transition("pointing_handle", info);
        }
        break;
      }
      case "selection": {
        switch (info.handle) {
          case "mobile_rotate":
          case "top_left_rotate":
          case "top_right_rotate":
          case "bottom_left_rotate":
          case "bottom_right_rotate": {
            this.parent.transition("pointing_rotate_handle", info);
            break;
          }
          case "top":
          case "right":
          case "bottom":
          case "left": {
            if (shouldEnterCropMode) {
              this.parent.transition("pointing_crop_handle", info);
            } else {
              this.parent.transition("pointing_resize_handle", info);
            }
            break;
          }
          case "top_left":
          case "top_right":
          case "bottom_left":
          case "bottom_right": {
            if (shouldEnterCropMode) {
              this.parent.transition("pointing_crop_handle", info);
            } else {
              this.parent.transition("pointing_resize_handle", info);
            }
            break;
          }
          default: {
            const hoveredShape = this.editor.getHoveredShape();
            if (hoveredShape && !this.editor.getSelectedShapeIds().includes(hoveredShape.id)) {
              this.onPointerDown({
                ...info,
                shape: hoveredShape,
                target: "shape"
              });
              return;
            }
            this.parent.transition("pointing_selection", info);
          }
        }
        break;
      }
    }
  };
  onDoubleClick = (info) => {
    if (this.editor.inputs.shiftKey || info.phase !== "up")
      return;
    switch (info.target) {
      case "canvas": {
        const hoveredShape = this.editor.getHoveredShape();
        const hitShape = hoveredShape && !this.editor.isShapeOfType(hoveredShape, "group") ? hoveredShape : this.editor.getSelectedShapeAtPoint(this.editor.inputs.currentPagePoint) ?? this.editor.getShapeAtPoint(this.editor.inputs.currentPagePoint, {
          margin: HIT_TEST_MARGIN / this.editor.getZoomLevel(),
          hitInside: false
        });
        const focusedGroupId = this.editor.getFocusedGroupId();
        if (hitShape) {
          if (this.editor.isShapeOfType(hitShape, "group")) {
            selectOnCanvasPointerUp(this.editor);
            return;
          } else {
            const parent = this.editor.getShape(hitShape.parentId);
            if (parent && this.editor.isShapeOfType(parent, "group")) {
              if (focusedGroupId && parent.id === focusedGroupId) {
              } else {
                selectOnCanvasPointerUp(this.editor);
                return;
              }
            }
          }
          this.onDoubleClick({
            ...info,
            shape: hitShape,
            target: "shape"
          });
          return;
        }
        if (!this.editor.inputs.shiftKey) {
          this.handleDoubleClickOnCanvas(info);
        }
        break;
      }
      case "selection": {
        if (this.editor.getInstanceState().isReadonly)
          break;
        const onlySelectedShape = this.editor.getOnlySelectedShape();
        if (onlySelectedShape) {
          const util = this.editor.getShapeUtil(onlySelectedShape);
          if (!this.canInteractWithShapeInReadOnly(onlySelectedShape)) {
            return;
          }
          if (info.handle === "right" || info.handle === "left" || info.handle === "top" || info.handle === "bottom") {
            const change = util.onDoubleClickEdge?.(onlySelectedShape);
            if (change) {
              this.editor.mark("double click edge");
              this.editor.updateShapes([change]);
              return;
            }
          }
          if (util.canCrop(onlySelectedShape) && !this.editor.isShapeOrAncestorLocked(onlySelectedShape)) {
            this.parent.transition("crop", info);
            return;
          }
          if (this.shouldStartEditingShape(onlySelectedShape)) {
            this.startEditingShape(onlySelectedShape, info);
          }
        }
        break;
      }
      case "shape": {
        const { shape } = info;
        const util = this.editor.getShapeUtil(shape);
        if (shape.type !== "video" && shape.type !== "embed" && this.editor.getInstanceState().isReadonly)
          break;
        if (util.onDoubleClick) {
          const change = util.onDoubleClick?.(shape);
          if (change) {
            this.editor.updateShapes([change]);
            return;
          } else if (util.canCrop(shape) && !this.editor.isShapeOrAncestorLocked(shape)) {
            this.editor.mark("select and crop");
            this.editor.select(info.shape?.id);
            this.parent.transition("crop", info);
            return;
          }
        }
        if (this.shouldStartEditingShape(shape)) {
          this.startEditingShape(shape, info);
        } else {
          this.handleDoubleClickOnCanvas(info);
        }
        break;
      }
      case "handle": {
        if (this.editor.getInstanceState().isReadonly)
          break;
        const { shape, handle } = info;
        const util = this.editor.getShapeUtil(shape);
        const changes = util.onDoubleClickHandle?.(shape, handle);
        if (changes) {
          this.editor.updateShapes([changes]);
        } else {
          if (this.shouldStartEditingShape(shape)) {
            this.startEditingShape(shape, info);
          }
        }
      }
    }
  };
  onRightClick = (info) => {
    switch (info.target) {
      case "canvas": {
        const hoveredShape = this.editor.getHoveredShape();
        const hitShape = hoveredShape && !this.editor.isShapeOfType(hoveredShape, "group") ? hoveredShape : this.editor.getShapeAtPoint(this.editor.inputs.currentPagePoint, {
          margin: HIT_TEST_MARGIN / this.editor.getZoomLevel(),
          hitInside: false,
          hitLabels: true,
          hitFrameInside: false,
          renderingOnly: true
        });
        if (hitShape) {
          this.onRightClick({
            ...info,
            shape: hitShape,
            target: "shape"
          });
          return;
        }
        const selectedShapeIds = this.editor.getSelectedShapeIds();
        const onlySelectedShape = this.editor.getOnlySelectedShape();
        const {
          inputs: { currentPagePoint }
        } = this.editor;
        if (selectedShapeIds.length > 1 || onlySelectedShape && !this.editor.getShapeUtil(onlySelectedShape).hideSelectionBoundsBg(onlySelectedShape)) {
          if (isPointInRotatedSelectionBounds(this.editor, currentPagePoint)) {
            this.onRightClick({
              ...info,
              target: "selection"
            });
            return;
          }
        }
        this.editor.selectNone();
        break;
      }
      case "shape": {
        const { selectedShapeIds } = this.editor.getCurrentPageState();
        const { shape } = info;
        const targetShape = this.editor.getOutermostSelectableShape(
          shape,
          (parent) => !selectedShapeIds.includes(parent.id)
        );
        if (!selectedShapeIds.includes(targetShape.id)) {
          this.editor.mark("selecting shape");
          this.editor.setSelectedShapes([targetShape.id]);
        }
        break;
      }
    }
  };
  onCancel = () => {
    if (this.editor.getFocusedGroupId() !== this.editor.getCurrentPageId() && this.editor.getSelectedShapeIds().length > 0) {
      this.editor.popFocusedGroupId();
    } else {
      this.editor.mark("clearing selection");
      this.editor.selectNone();
    }
  };
  onKeyDown = (info) => {
    switch (info.code) {
      case "ArrowLeft":
      case "ArrowRight":
      case "ArrowUp":
      case "ArrowDown": {
        this.nudgeSelectedShapes(false);
        break;
      }
    }
  };
  onKeyRepeat = (info) => {
    switch (info.code) {
      case "ArrowLeft":
      case "ArrowRight":
      case "ArrowUp":
      case "ArrowDown": {
        this.nudgeSelectedShapes(true);
        break;
      }
    }
  };
  onKeyUp = (info) => {
    switch (info.code) {
      case "Enter": {
        const selectedShapes = this.editor.getSelectedShapes();
        if (selectedShapes.every((shape) => this.editor.isShapeOfType(shape, "group"))) {
          this.editor.setSelectedShapes(
            selectedShapes.flatMap((shape) => this.editor.getSortedChildIdsForParent(shape.id))
          );
          return;
        }
        const onlySelectedShape = this.editor.getOnlySelectedShape();
        if (onlySelectedShape && this.shouldStartEditingShape(onlySelectedShape)) {
          this.startEditingShape(onlySelectedShape, {
            ...info,
            target: "shape",
            shape: onlySelectedShape
          });
          return;
        }
        if (getShouldEnterCropMode(this.editor)) {
          this.parent.transition("crop", info);
        }
        break;
      }
    }
  };
  shouldStartEditingShape(shape = this.editor.getOnlySelectedShape()) {
    if (!shape)
      return false;
    if (this.editor.isShapeOrAncestorLocked(shape) && shape.type !== "embed")
      return false;
    if (!this.canInteractWithShapeInReadOnly(shape))
      return false;
    return this.editor.getShapeUtil(shape).canEdit(shape);
  }
  startEditingShape(shape, info) {
    if (this.editor.isShapeOrAncestorLocked(shape) && shape.type !== "embed")
      return;
    this.editor.mark("editing shape");
    this.editor.setEditingShape(shape.id);
    this.parent.transition("editing_shape", info);
  }
  isDarwin = window.navigator.userAgent.toLowerCase().indexOf("mac") > -1;
  handleDoubleClickOnCanvas(info) {
    if (this.editor.getInstanceState().isReadonly)
      return;
    this.editor.mark("creating text shape");
    const id = createShapeId();
    const { x, y } = this.editor.inputs.currentPagePoint;
    this.editor.createShapes([
      {
        id,
        type: "text",
        x,
        y,
        props: {
          text: "",
          autoSize: true
        }
      }
    ]);
    const shape = this.editor.getShape(id);
    if (!shape)
      return;
    const util = this.editor.getShapeUtil(shape);
    if (this.editor.getInstanceState().isReadonly) {
      if (!util.canEditInReadOnly(shape)) {
        return;
      }
    }
    this.editor.setEditingShape(id);
    this.editor.select(id);
    this.parent.transition("editing_shape", info);
  }
  nudgeSelectedShapes(ephemeral = false) {
    const {
      editor: {
        inputs: { keys }
      }
    } = this;
    const shiftKey = keys.has("ShiftLeft");
    const delta = new Vec2d(0, 0);
    if (keys.has("ArrowLeft"))
      delta.x -= 1;
    if (keys.has("ArrowRight"))
      delta.x += 1;
    if (keys.has("ArrowUp"))
      delta.y -= 1;
    if (keys.has("ArrowDown"))
      delta.y += 1;
    if (delta.equals(new Vec2d(0, 0)))
      return;
    if (!ephemeral)
      this.editor.mark("nudge shapes");
    const { gridSize } = this.editor.getDocumentSettings();
    const step = this.editor.getInstanceState().isGridMode ? shiftKey ? gridSize * GRID_INCREMENT : gridSize : shiftKey ? MAJOR_NUDGE_FACTOR : MINOR_NUDGE_FACTOR;
    this.editor.nudgeShapes(this.editor.getSelectedShapeIds(), delta.mul(step));
  }
  canInteractWithShapeInReadOnly(shape) {
    if (!this.editor.getInstanceState().isReadonly)
      return true;
    const util = this.editor.getShapeUtil(shape);
    if (util.canEditInReadOnly(shape))
      return true;
    return false;
  }
}
const MAJOR_NUDGE_FACTOR = 10;
const MINOR_NUDGE_FACTOR = 1;
const GRID_INCREMENT = 5;
function isPointInRotatedSelectionBounds(editor, point) {
  const selectionBounds = editor.getSelectionRotatedPageBounds();
  if (!selectionBounds)
    return false;
  const selectionRotation = editor.getSelectionRotation();
  if (!selectionRotation)
    return selectionBounds.containsPoint(point);
  return pointInPolygon(
    point,
    selectionBounds.corners.map((c) => Vec2d.RotWith(c, selectionBounds.point, selectionRotation))
  );
}
export {
  GRID_INCREMENT,
  Idle,
  MAJOR_NUDGE_FACTOR,
  MINOR_NUDGE_FACTOR
};
//# sourceMappingURL=Idle.mjs.map
