import { Behaviour } from "@needle-tools/engine";
import { Vector2, Raycaster, Vector3, Plane } from "three";

export class ARObjectController extends Behaviour {
  private raycaster: Raycaster = new Raycaster();
  private touchPos: Vector2 = new Vector2();
  private plane: Plane = new Plane(new Vector3(0, 1, 0), 0);

  private initialPinchDistance: number = 0;
  private initialScale: Vector3 = new Vector3();
  private isScaling: boolean = false;

  onEnable(): void {
    const canvas = this.context.renderer.domElement;
    canvas.addEventListener("touchstart", this.onTouchStart);
    canvas.addEventListener("touchmove", this.onTouchMove);
    canvas.addEventListener("touchend", this.onTouchEnd);
  }

  onDisable(): void {
    const canvas = this.context.renderer.domElement;
    canvas.removeEventListener("touchstart", this.onTouchStart);
    canvas.removeEventListener("touchmove", this.onTouchMove);
    canvas.removeEventListener("touchend", this.onTouchEnd);
  }

  private onTouchStart = (event: TouchEvent): void => {
    if (event.touches.length === 2) {
      this.isScaling = true;
      const touch1 = event.touches[0];
      const touch2 = event.touches[1];
      this.initialPinchDistance = Math.hypot(
        touch2.clientX - touch1.clientX,
        touch2.clientY - touch1.clientY
      );
      this.initialScale.copy(this.gameObject.scale);
    }
  };

  private onTouchMove = (event: TouchEvent): void => {
    event.preventDefault();

    if (this.isScaling && event.touches.length === 2) {
      const touch1 = event.touches[0];
      const touch2 = event.touches[1];
      const currentDistance = Math.hypot(
        touch2.clientX - touch1.clientX,
        touch2.clientY - touch1.clientY
      );
      const scaleFactor = currentDistance / this.initialPinchDistance;
      const newScale = this.initialScale.clone().multiplyScalar(scaleFactor);
      this.gameObject.scale.copy(newScale);
    } else if (event.touches.length === 1 && !this.isScaling) {
      const touch = event.touches[0];
      const canvas = this.context.renderer.domElement;
      const rect = canvas.getBoundingClientRect();
      this.touchPos.set(
        ((touch.clientX - rect.left) / rect.width) * 2 - 1,
        -((touch.clientY - rect.top) / rect.height) * 2 + 1
      );
      this.raycaster.setFromCamera(this.touchPos, this.context.mainCamera);
      const intersection = new Vector3();
      if (this.raycaster.ray.intersectPlane(this.plane, intersection)) {
        this.gameObject.position.copy(intersection);
      }
    }
  };

  private onTouchEnd = (event: TouchEvent): void => {
    if (event.touches.length < 2) {
      this.isScaling = false;
    }
  };
}
