import * as THREE from 'three'

export class EventManager {
  private mouse: THREE.Vector2
  private raycaster: THREE.Raycaster
  private mouseWorldPosition: THREE.Vector3
  private camera: THREE.PerspectiveCamera
  private renderer: THREE.WebGLRenderer

  constructor(
    mouse: THREE.Vector2,
    raycaster: THREE.Raycaster,
    mouseWorldPosition: THREE.Vector3,
    camera: THREE.PerspectiveCamera,
    renderer: THREE.WebGLRenderer
  ) {
    this.mouse = mouse
    this.raycaster = raycaster
    this.mouseWorldPosition = mouseWorldPosition
    this.camera = camera
    this.renderer = renderer
  }

  setupEventListeners(): void {
    // Get the canvas element to ensure we're listening on the right element
    const canvas = this.renderer.domElement

    // Mouse move event - listen on both window and canvas for better coverage
    const handleMouseMove = (event: MouseEvent) => {
      // Calculate mouse position relative to the renderer's canvas
      const rect = canvas.getBoundingClientRect()
      this.mouse.x = ((event.clientX - rect.left) / rect.width) * 2 - 1
      this.mouse.y = -((event.clientY - rect.top) / rect.height) * 2 + 1

      // Update raycaster
      this.raycaster.setFromCamera(this.mouse, this.camera)
      
      // Project mouse position to the Z=0 plane (where most objects are)
      const targetPlane = new THREE.Plane(new THREE.Vector3(0, 0, 1), 0)
      const intersection = new THREE.Vector3()
      this.raycaster.ray.intersectPlane(targetPlane, intersection)
      
      if (intersection) {
        this.mouseWorldPosition.copy(intersection)
      } else {
        // Fallback: use a fixed distance projection
        const distance = Math.abs(this.camera.position.z)
        const direction = this.raycaster.ray.direction.clone()
        direction.multiplyScalar(distance)
        this.mouseWorldPosition.copy(this.camera.position).add(direction)
      }
    }

    // Listen on both window and canvas
    window.addEventListener('mousemove', handleMouseMove)
    canvas.addEventListener('mousemove', handleMouseMove)

    // Window resize event
    window.addEventListener('resize', () => {
      this.camera.aspect = window.innerWidth / window.innerHeight
      this.camera.updateProjectionMatrix()
      this.renderer.setSize(window.innerWidth, window.innerHeight)
    })
  }
}
