import config from '@/application/config'
import { getTile, tileToWorldXY } from '@/composables/mapComposable'
import { useGameStore } from '@/stores/gameStore'
import { ref, type Ref } from 'vue'

export function useGamePointerHandlers(scene: Phaser.Scene, layer: Phaser.Tilemaps.TilemapLayer, waypoint: Ref<{ visible: boolean; x: number; y: number }>, camera: Phaser.Cameras.Scene2D.Camera) {
  const gameStore = useGameStore()
  const pointerStartPosition = ref({ x: 0, y: 0 })
  const dragThreshold = 5 // pixels

  function updateWaypoint(worldX: number, worldY: number) {
    const pointerTile = getTile(layer, worldX, worldY)
    if (!pointerTile) {
      waypoint.value.visible = false
      return
    }
    const worldPoint = tileToWorldXY(layer, pointerTile.x, pointerTile.y)
    if (!worldPoint.worldPositionX || !worldPoint.worldPositionX) return

    waypoint.value = {
      visible: true,
      x: worldPoint.worldPositionX,
      y: worldPoint.worldPositionY + config.tile_size.height + 15
    }
  }

  function handlePointerDown(pointer: Phaser.Input.Pointer) {
    pointerStartPosition.value = pointer.position
    gameStore.setPlayerDraggingCamera(true)
  }

  function handlePointerMove(pointer: Phaser.Input.Pointer) {
    updateWaypoint(pointer.worldX, pointer.worldY)

    if (!gameStore.game.isPlayerDraggingCamera) return

    // If the distance is less than the drag threshold, return
    // We do this to prevent the camera from scrolling too quickly
    const distance = Phaser.Math.Distance.Between(pointerStartPosition.value.x, pointerStartPosition.value.y, pointer.x, pointer.y)
    if (distance <= dragThreshold) return

    camera.setScroll(camera.scrollX - (pointer.x - pointer.prevPosition.x) / camera.zoom, camera.scrollY - (pointer.y - pointer.prevPosition.y) / camera.zoom)
  }

  function handlePointerUp(pointer: Phaser.Input.Pointer) {
    gameStore.setPlayerDraggingCamera(false)

    const pointerTile = getTile(layer, pointer.worldX, pointer.worldY)
    if (!pointerTile) return

    gameStore.connection?.emit('map:character:move', {
      positionX: pointerTile.x,
      positionY: pointerTile.y
    })
  }

  const setupPointerHandlers = () => {
    scene.input.on(Phaser.Input.Events.POINTER_DOWN, handlePointerDown)
    scene.input.on(Phaser.Input.Events.POINTER_MOVE, handlePointerMove)
    scene.input.on(Phaser.Input.Events.POINTER_UP, handlePointerUp)
  }

  const cleanupPointerHandlers = () => {
    scene.input.off(Phaser.Input.Events.POINTER_DOWN, handlePointerDown)
    scene.input.off(Phaser.Input.Events.POINTER_MOVE, handlePointerMove)
    scene.input.off(Phaser.Input.Events.POINTER_UP, handlePointerUp)
  }

  return { setupPointerHandlers, cleanupPointerHandlers }
}
