import { __decorate } from "../_virtual/_@oxc-project_runtime@0.95.0/helpers/decorate.js";
import { panZoomTransformContext } from "./panZoomTransformContext.js";
import { getCornerPoint, getOppositeCorner } from "./transformUtils.js";
import { calculateDragBounds, calculateResizeBounds, getResizeHandleCursor } from "./transformCalculations.js";
import { consume } from "@lit/context";
import { LitElement, css, html } from "lit";
import { customElement, property, state } from "lit/decorators.js";
import { styleMap } from "lit/directives/style-map.js";

//#region src/gui/EFTransformHandles.ts
const DEFAULT_MIN_SIZE = 10;
let EFTransformHandles = class EFTransformHandles$1 extends LitElement {
	constructor(..._args) {
		super(..._args);
		this.bounds = {
			x: 0,
			y: 0,
			width: 100,
			height: 100
		};
		this.minSize = DEFAULT_MIN_SIZE;
		this.canvasScale = 1;
		this.enableRotation = false;
		this.enableResize = true;
		this.cornersOnly = false;
		this.lockAspectRatio = false;
		this.enableDrag = true;
		this.interactionMode = "idle";
		this.activeResizeHandle = null;
		this.mouseStart = null;
		this.initialBounds = null;
		this.handleMouseDown = (e) => {
			if (!this.enableDrag) return;
			e.stopPropagation();
			this.interactionMode = this.transitionInteractionMode("mousedown-drag");
			this.mouseStart = {
				x: e.clientX,
				y: e.clientY
			};
			this.initialBounds = { ...this.bounds };
			document.addEventListener("mousemove", this.handleMouseMove);
			document.addEventListener("mouseup", this.handleMouseUp);
		};
		this.handleResizeMouseDown = (e, handle) => {
			if (!this.enableResize) return;
			e.stopPropagation();
			e.preventDefault();
			this.interactionMode = this.transitionInteractionMode("mousedown-resize");
			this.activeResizeHandle = handle;
			this.mouseStart = {
				x: e.clientX,
				y: e.clientY
			};
			this.initialBounds = { ...this.bounds };
			document.addEventListener("mousemove", this.handleMouseMove);
			document.addEventListener("mouseup", this.handleMouseUp);
		};
		this.handleRotateMouseDown = (e) => {
			if (!this.enableRotation) return;
			e.stopPropagation();
			this.interactionMode = this.transitionInteractionMode("mousedown-rotate");
			this.mouseStart = {
				x: e.clientX,
				y: e.clientY
			};
			this.initialBounds = { ...this.bounds };
			document.addEventListener("mousemove", this.handleMouseMove);
			document.addEventListener("mouseup", this.handleMouseUp);
		};
		this.handleMouseMove = (e) => {
			if (!this.mouseStart || !this.initialBounds) return;
			const screenDeltaX = e.clientX - this.mouseStart.x;
			const screenDeltaY = e.clientY - this.mouseStart.y;
			switch (this.interactionMode) {
				case "dragging": {
					const zoomScale = this.getZoomScale();
					const initialCanvas = this.screenToCanvas(this.initialBounds);
					const newPosition = calculateDragBounds({
						x: initialCanvas.x,
						y: initialCanvas.y
					}, screenDeltaX, screenDeltaY, zoomScale);
					this.dispatchBoundsChange({
						...newPosition,
						width: initialCanvas.width,
						height: initialCanvas.height,
						rotation: this.initialBounds.rotation
					});
					break;
				}
				case "resizing": {
					if (!this.activeResizeHandle) return;
					const zoomScale = this.getZoomScale();
					const initialCanvas = this.screenToCanvas(this.initialBounds);
					const rotation = this.enableRotation ? this.initialBounds.rotation ?? 0 : 0;
					const oppositeCorner = getOppositeCorner(this.activeResizeHandle);
					const rotationRadians = rotation * Math.PI / 180;
					const fixedCorner = getCornerPoint(initialCanvas.x, initialCanvas.y, initialCanvas.width, initialCanvas.height, rotationRadians, oppositeCorner.x, oppositeCorner.y);
					const newCanvasBounds = calculateResizeBounds({
						width: initialCanvas.width,
						height: initialCanvas.height
					}, {
						x: initialCanvas.x,
						y: initialCanvas.y
					}, fixedCorner, this.activeResizeHandle, screenDeltaX, screenDeltaY, rotation, this.minSize / zoomScale, zoomScale, {
						lockAspectRatio: this.lockAspectRatio || e.shiftKey,
						resizeFromCenter: e.ctrlKey || e.metaKey
					});
					newCanvasBounds.rotation = this.initialBounds.rotation;
					this.dispatchBoundsChange(newCanvasBounds);
					break;
				}
				case "rotating": {
					const overlayRect = this.offsetParent?.getBoundingClientRect() ?? {
						left: 0,
						top: 0
					};
					const centerX = overlayRect.left + this.initialBounds.x + this.initialBounds.width / 2;
					const centerY = overlayRect.top + this.initialBounds.y + this.initialBounds.height / 2;
					const startAngle = Math.atan2(this.mouseStart.y - centerY, this.mouseStart.x - centerX) * (180 / Math.PI) + 90;
					let deltaAngle = Math.atan2(e.clientY - centerY, e.clientX - centerX) * (180 / Math.PI) + 90 - startAngle;
					while (deltaAngle > 180) deltaAngle -= 360;
					while (deltaAngle < -180) deltaAngle += 360;
					let newRotation = (this.initialBounds.rotation ?? 0) + deltaAngle;
					if (this.rotationStep !== void 0 && this.rotationStep > 0) newRotation = Math.round(newRotation / this.rotationStep) * this.rotationStep;
					this.dispatchEvent(new CustomEvent("rotation-change", {
						detail: { rotation: newRotation },
						bubbles: true,
						composed: true
					}));
					break;
				}
				case "idle": break;
			}
		};
		this.handleMouseUp = () => {
			this.cleanup();
		};
	}
	static {
		this.styles = css`
    :host {
      display: block;
      position: absolute;
      pointer-events: none;
    }
    .overlay {
      position: absolute;
      border: 2px solid var(--ef-transform-handles-border-color, var(--ef-color-primary));
      pointer-events: none;
    }
    .overlay.dragging {
      border-color: var(--ef-transform-handles-dragging-border-color, var(--ef-color-primary));
    }
    .drag-area {
      position: absolute;
      inset: 0;
      cursor: move;
      pointer-events: none;
    }
    /* Only enable pointer events when actively dragging */
    .drag-area:active {
      pointer-events: auto;
    }
    .handle {
      position: absolute;
      width: 8px;
      height: 8px;
      background: var(--ef-transform-handles-handle-color, var(--ef-color-bg-elevated));
      border: 1px solid var(--ef-transform-handles-handle-border-color, var(--ef-color-primary));
      pointer-events: auto;
      /* Only capture pointer events, allow wheel events to pass through */
      touch-action: none;
    }
    .handle.nw { top: -4px; left: -4px; }
    .handle.n { top: -4px; left: 50%; transform: translateX(-50%); }
    .handle.ne { top: -4px; right: -4px; }
    .handle.e { top: 50%; right: -4px; transform: translateY(-50%); }
    .handle.se { bottom: -4px; right: -4px; }
    .handle.s { bottom: -4px; left: 50%; transform: translateX(-50%); }
    .handle.sw { bottom: -4px; left: -4px; }
    .handle.w { top: 50%; left: -4px; transform: translateY(-50%); }
    .rotate-handle {
      position: absolute;
      top: -30px;
      left: 50%;
      transform: translateX(-50%);
      cursor: grab;
      pointer-events: auto;
      /* Only capture pointer events, allow wheel events to pass through */
      touch-action: none;
    }
    .rotate-handle-circle {
      width: 24px;
      height: 24px;
      background: var(--ef-transform-handles-rotate-handle-color, var(--ef-color-success));
      border: 2px solid var(--ef-color-bg-elevated);
      border-radius: 50%;
      display: flex;
      align-items: center;
      justify-content: center;
    }
    .rotate-handle-circle span {
      font-size: 12px;
      color: white;
    }
  `;
	}
	/**
	* Single source of truth for zoom scale.
	* Priority: context > prop > 1.0
	*/
	getZoomScale() {
		return this.panZoomTransformFromContext?.scale ?? this.canvasScale ?? 1;
	}
	/**
	* Convert screen pixel bounds to canvas coordinates.
	*/
	screenToCanvas(bounds) {
		const scale = this.getZoomScale();
		return {
			x: bounds.x / scale,
			y: bounds.y / scale,
			width: bounds.width / scale,
			height: bounds.height / scale,
			rotation: bounds.rotation
		};
	}
	connectedCallback() {
		super.connectedCallback();
		this.resizeObserver = new ResizeObserver(() => {});
		if (this.offsetParent) this.resizeObserver.observe(this.offsetParent);
		this.addEventListener("wheel", (e) => {
			if (this.interactionMode === "idle") {
				const panZoom = this.closest("ef-pan-zoom");
				if (panZoom) {
					const wheelEvent = new WheelEvent("wheel", {
						bubbles: true,
						cancelable: true,
						clientX: e.clientX,
						clientY: e.clientY,
						deltaX: e.deltaX,
						deltaY: e.deltaY,
						deltaZ: e.deltaZ,
						deltaMode: e.deltaMode,
						ctrlKey: e.ctrlKey,
						metaKey: e.metaKey,
						shiftKey: e.shiftKey,
						altKey: e.altKey
					});
					panZoom.dispatchEvent(wheelEvent);
				}
			}
		}, { passive: true });
	}
	disconnectedCallback() {
		super.disconnectedCallback();
		this.resizeObserver?.disconnect();
		this.cleanup();
	}
	/**
	* Transition interaction mode state machine.
	* Ensures only one mode is active at a time (invariant).
	*/
	transitionInteractionMode(event) {
		if (event === "mouseup") return "idle";
		if (this.interactionMode !== "idle") return this.interactionMode;
		switch (event) {
			case "mousedown-drag": return "dragging";
			case "mousedown-resize": return "resizing";
			case "mousedown-rotate": return "rotating";
			default: return "idle";
		}
	}
	/**
	* Dispatch bounds change event (one-way data flow).
	* Parent updates element, then reads element and updates handle bounds prop.
	* We don't modify this.bounds directly - always render from prop.
	*/
	dispatchBoundsChange(bounds) {
		this.dispatchEvent(new CustomEvent("bounds-change", {
			detail: { bounds },
			bubbles: true,
			composed: true
		}));
	}
	cleanup() {
		this.interactionMode = this.transitionInteractionMode("mouseup");
		this.activeResizeHandle = null;
		this.mouseStart = null;
		this.initialBounds = null;
		document.removeEventListener("mousemove", this.handleMouseMove);
		document.removeEventListener("mouseup", this.handleMouseUp);
	}
	render() {
		const currentBounds = this.bounds;
		const rotation = this.enableRotation ? currentBounds.rotation ?? 0 : 0;
		const overlayStyles = {
			left: `${currentBounds.x}px`,
			top: `${currentBounds.y}px`,
			width: `${currentBounds.width}px`,
			height: `${currentBounds.height}px`
		};
		if (this.enableRotation && rotation !== 0) {
			overlayStyles.transform = `rotate(${rotation}deg)`;
			overlayStyles.transformOrigin = "center";
		}
		const handles = this.cornersOnly ? [
			"nw",
			"ne",
			"se",
			"sw"
		] : [
			"nw",
			"n",
			"ne",
			"e",
			"se",
			"s",
			"sw",
			"w"
		];
		return html`
      <div
        class="overlay ${this.interactionMode === "dragging" ? "dragging" : ""}"
        style=${styleMap(overlayStyles)}
      >
        ${this.enableDrag ? html`
              <div
                class="drag-area"
                @mousedown=${this.handleMouseDown}
              ></div>
            ` : ""}
        ${this.enableResize ? handles.map((handle) => {
			return html`
                <div
                  class="handle ${handle}"
                      style=${styleMap({ cursor: getResizeHandleCursor(handle, this.enableRotation ? currentBounds.rotation ?? 0 : 0) })}
                  @mousedown=${(e) => this.handleResizeMouseDown(e, handle)}
                ></div>
                  `;
		}) : ""}
        ${this.enableRotation ? html`
              <div class="rotate-handle" @mousedown=${this.handleRotateMouseDown}>
                <div class="rotate-handle-circle">
                  <span>↻</span>
                </div>
              </div>
            ` : ""}
      </div>
    `;
	}
};
__decorate([property({ type: Object })], EFTransformHandles.prototype, "bounds", void 0);
__decorate([property({ type: Number })], EFTransformHandles.prototype, "minSize", void 0);
__decorate([property({ type: String })], EFTransformHandles.prototype, "target", void 0);
__decorate([consume({
	context: panZoomTransformContext,
	subscribe: true
})], EFTransformHandles.prototype, "panZoomTransformFromContext", void 0);
__decorate([property({
	type: Number,
	attribute: "canvas-scale"
})], EFTransformHandles.prototype, "canvasScale", void 0);
__decorate([property({
	type: Boolean,
	attribute: "enable-rotation"
})], EFTransformHandles.prototype, "enableRotation", void 0);
__decorate([property({
	type: Boolean,
	attribute: "enable-resize"
})], EFTransformHandles.prototype, "enableResize", void 0);
__decorate([property({
	type: Boolean,
	attribute: "corners-only"
})], EFTransformHandles.prototype, "cornersOnly", void 0);
__decorate([property({
	type: Boolean,
	attribute: "lock-aspect-ratio"
})], EFTransformHandles.prototype, "lockAspectRatio", void 0);
__decorate([property({
	type: Boolean,
	attribute: "enable-drag"
})], EFTransformHandles.prototype, "enableDrag", void 0);
__decorate([property({
	type: Number,
	attribute: "rotation-step"
})], EFTransformHandles.prototype, "rotationStep", void 0);
__decorate([state()], EFTransformHandles.prototype, "interactionMode", void 0);
EFTransformHandles = __decorate([customElement("ef-transform-handles")], EFTransformHandles);

//#endregion
export { EFTransformHandles };
//# sourceMappingURL=EFTransformHandles.js.map