<template>
  <Image :depth="1" texture="waypoint" :x="waypoint.x" :y="waypoint.y" :visible="waypoint.visible" />
</template>

<script setup lang="ts">
import { Image, useScene } from 'phavuer'
import { onBeforeUnmount, ref } from 'vue'
import { usePointerHandlers } from '@/composables/usePointerHandlers'
import { useCameraControls } from '@/composables/useCameraControls'

// Types
type WayPoint = { visible: boolean; x: number; y: number }

// Props
const props = defineProps<{ layer: Phaser.Tilemaps.TilemapLayer }>()

// Constants
const ZOOM_SETTINGS = {
  WHEEL_FACTOR: 0.005,
  KEY_FACTOR: 0.3,
  MIN: 1,
  MAX: 3
} as const

// Setup
const scene = useScene()
const waypoint = ref<WayPoint>({ visible: false, x: 0, y: 0 })
const { camera } = useCameraControls(scene)
const { setupPointerHandlers, cleanupPointerHandlers } = usePointerHandlers(scene, props.layer, waypoint, camera)

// Handlers
function handleScrollZoom(pointer: Phaser.Input.Pointer) {
  if (!(pointer.event instanceof WheelEvent && pointer.event.shiftKey)) return

  const zoomLevel = Phaser.Math.Clamp(
    camera.zoom - pointer.event.deltaY * ZOOM_SETTINGS.WHEEL_FACTOR,
    ZOOM_SETTINGS.MIN,
    ZOOM_SETTINGS.MAX
  )
  camera.setZoom(zoomLevel)
}

function handleKeyComboZoom(event: { keyCodes: number[] }) {
  const deltaY = event.keyCodes[1] === 38 ? 1 : -1 // 38 is Up, 40 is Down
  const zoomLevel = Phaser.Math.Clamp(
    camera.zoom + deltaY * ZOOM_SETTINGS.KEY_FACTOR,
    ZOOM_SETTINGS.MIN,
    ZOOM_SETTINGS.MAX
  )
  camera.setZoom(zoomLevel)
}

// Event setup
setupPointerHandlers()
scene.input.keyboard?.createCombo([16, 38], { resetOnMatch: true }) // Shift + Up
scene.input.keyboard?.createCombo([16, 40], { resetOnMatch: true }) // Shift + Down
scene.input.keyboard?.on('keycombomatch', handleKeyComboZoom)
scene.input.on(Phaser.Input.Events.POINTER_WHEEL, handleScrollZoom)

// Cleanup
onBeforeUnmount(() => {
  cleanupPointerHandlers()
  scene.input.keyboard?.off('keycombomatch')
  scene.input.off(Phaser.Input.Events.POINTER_WHEEL, handleScrollZoom)
})
</script>